(* Generated by coq-of-rust *)
Require Import CoqOfRust.CoqOfRust.

Module generic_token_account.
  Definition value_SPL_TOKEN_ACCOUNT_MINT_OFFSET : Value.t :=
    M.run ltac:(M.monadic (M.alloc (| Value.Integer 0 |))).
  
  Definition value_SPL_TOKEN_ACCOUNT_OWNER_OFFSET : Value.t :=
    M.run ltac:(M.monadic (M.alloc (| Value.Integer 32 |))).
  
  (* Trait *)
  Module GenericTokenAccount.
    Definition unpack_account_owner_unchecked
        (Self : Ty.t)
        (τ : list Ty.t)
        (α : list Value.t)
        : M :=
      match τ, α with
      | [], [ account_data ] =>
        ltac:(M.monadic
          (let account_data := M.alloc (| account_data |) in
          M.call_closure (|
            M.get_trait_method (|
              "spl_token_2022::generic_token_account::GenericTokenAccount",
              Self,
              [],
              "unpack_pubkey_unchecked",
              []
            |),
            [
              M.read (| account_data |);
              M.read (|
                M.get_constant (|
                  "spl_token_2022::generic_token_account::SPL_TOKEN_ACCOUNT_OWNER_OFFSET"
                |)
              |)
            ]
          |)))
      | _, _ => M.impossible
      end.
    
    Axiom ProvidedMethod_unpack_account_owner_unchecked :
      M.IsProvidedMethod
        "spl_token_2022::generic_token_account::GenericTokenAccount"
        "unpack_account_owner_unchecked"
        unpack_account_owner_unchecked.
    Definition unpack_account_mint_unchecked (Self : Ty.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match τ, α with
      | [], [ account_data ] =>
        ltac:(M.monadic
          (let account_data := M.alloc (| account_data |) in
          M.call_closure (|
            M.get_trait_method (|
              "spl_token_2022::generic_token_account::GenericTokenAccount",
              Self,
              [],
              "unpack_pubkey_unchecked",
              []
            |),
            [
              M.read (| account_data |);
              M.read (|
                M.get_constant (|
                  "spl_token_2022::generic_token_account::SPL_TOKEN_ACCOUNT_MINT_OFFSET"
                |)
              |)
            ]
          |)))
      | _, _ => M.impossible
      end.
    
    Axiom ProvidedMethod_unpack_account_mint_unchecked :
      M.IsProvidedMethod
        "spl_token_2022::generic_token_account::GenericTokenAccount"
        "unpack_account_mint_unchecked"
        unpack_account_mint_unchecked.
    Definition unpack_pubkey_unchecked (Self : Ty.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match τ, α with
      | [], [ account_data; offset ] =>
        ltac:(M.monadic
          (let account_data := M.alloc (| account_data |) in
          let offset := M.alloc (| offset |) in
          M.call_closure (|
            M.get_function (|
              "bytemuck::from_bytes",
              [ Ty.path "solana_program::pubkey::Pubkey" ]
            |),
            [
              M.call_closure (|
                M.get_trait_method (|
                  "core::ops::index::Index",
                  Ty.apply (Ty.path "slice") [ Ty.path "u8" ],
                  [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ],
                  "index",
                  []
                |),
                [
                  M.read (| account_data |);
                  Value.StructRecord
                    "core::ops::range::Range"
                    [
                      ("start", M.read (| offset |));
                      ("end_",
                        BinOp.Panic.add (|
                          Integer.Usize,
                          M.read (| offset |),
                          M.read (| M.get_constant (| "solana_program::pubkey::PUBKEY_BYTES" |) |)
                        |))
                    ]
                ]
              |)
            ]
          |)))
      | _, _ => M.impossible
      end.
    
    Axiom ProvidedMethod_unpack_pubkey_unchecked :
      M.IsProvidedMethod
        "spl_token_2022::generic_token_account::GenericTokenAccount"
        "unpack_pubkey_unchecked"
        unpack_pubkey_unchecked.
    Definition unpack_account_owner (Self : Ty.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match τ, α with
      | [], [ account_data ] =>
        ltac:(M.monadic
          (let account_data := M.alloc (| account_data |) in
          M.read (|
            M.match_operator (|
              M.alloc (| Value.Tuple [] |),
              [
                fun γ =>
                  ltac:(M.monadic
                    (let γ :=
                      M.use
                        (M.alloc (|
                          M.call_closure (|
                            M.get_trait_method (|
                              "spl_token_2022::generic_token_account::GenericTokenAccount",
                              Self,
                              [],
                              "valid_account_data",
                              []
                            |),
                            [ M.read (| account_data |) ]
                          |)
                        |)) in
                    let _ := M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                    M.alloc (|
                      Value.StructTuple
                        "core::option::Option::Some"
                        [
                          M.call_closure (|
                            M.get_trait_method (|
                              "spl_token_2022::generic_token_account::GenericTokenAccount",
                              Self,
                              [],
                              "unpack_account_owner_unchecked",
                              []
                            |),
                            [ M.read (| account_data |) ]
                          |)
                        ]
                    |)));
                fun γ =>
                  ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |)))
              ]
            |)
          |)))
      | _, _ => M.impossible
      end.
    
    Axiom ProvidedMethod_unpack_account_owner :
      M.IsProvidedMethod
        "spl_token_2022::generic_token_account::GenericTokenAccount"
        "unpack_account_owner"
        unpack_account_owner.
    Definition unpack_account_mint (Self : Ty.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match τ, α with
      | [], [ account_data ] =>
        ltac:(M.monadic
          (let account_data := M.alloc (| account_data |) in
          M.read (|
            M.match_operator (|
              M.alloc (| Value.Tuple [] |),
              [
                fun γ =>
                  ltac:(M.monadic
                    (let γ :=
                      M.use
                        (M.alloc (|
                          M.call_closure (|
                            M.get_trait_method (|
                              "spl_token_2022::generic_token_account::GenericTokenAccount",
                              Self,
                              [],
                              "valid_account_data",
                              []
                            |),
                            [ M.read (| account_data |) ]
                          |)
                        |)) in
                    let _ := M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                    M.alloc (|
                      Value.StructTuple
                        "core::option::Option::Some"
                        [
                          M.call_closure (|
                            M.get_trait_method (|
                              "spl_token_2022::generic_token_account::GenericTokenAccount",
                              Self,
                              [],
                              "unpack_account_mint_unchecked",
                              []
                            |),
                            [ M.read (| account_data |) ]
                          |)
                        ]
                    |)));
                fun γ =>
                  ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |)))
              ]
            |)
          |)))
      | _, _ => M.impossible
      end.
    
    Axiom ProvidedMethod_unpack_account_mint :
      M.IsProvidedMethod
        "spl_token_2022::generic_token_account::GenericTokenAccount"
        "unpack_account_mint"
        unpack_account_mint.
  End GenericTokenAccount.
  
  Definition value_ACCOUNT_INITIALIZED_INDEX : Value.t :=
    M.run ltac:(M.monadic (M.alloc (| Value.Integer 108 |))).
  
  (*
  pub fn is_initialized_account(account_data: &[u8]) -> bool {
      *account_data
          .get(ACCOUNT_INITIALIZED_INDEX)
          .unwrap_or(&(AccountState::Uninitialized as u8))
          != AccountState::Uninitialized as u8
  }
  *)
  Definition is_initialized_account (τ : list Ty.t) (α : list Value.t) : M :=
    match τ, α with
    | [], [ account_data ] =>
      ltac:(M.monadic
        (let account_data := M.alloc (| account_data |) in
        BinOp.Pure.ne
          (M.read (|
            M.call_closure (|
              M.get_associated_function (|
                Ty.apply
                  (Ty.path "core::option::Option")
                  [ Ty.apply (Ty.path "&") [ Ty.path "u8" ] ],
                "unwrap_or",
                []
              |),
              [
                M.call_closure (|
                  M.get_associated_function (|
                    Ty.apply (Ty.path "slice") [ Ty.path "u8" ],
                    "get",
                    [ Ty.path "usize" ]
                  |),
                  [
                    M.read (| account_data |);
                    M.read (|
                      M.get_constant (|
                        "spl_token_2022::generic_token_account::ACCOUNT_INITIALIZED_INDEX"
                      |)
                    |)
                  ]
                |);
                M.alloc (| M.rust_cast (Value.Integer 0) |)
              ]
            |)
          |))
          (M.rust_cast (Value.Integer 0))))
    | _, _ => M.impossible
    end.
End generic_token_account.
