From aaa5adb0a67d3150b474c05f86e677c01843e450 Mon Sep 17 00:00:00 2001 From: Jack May Date: Mon, 21 Sep 2020 13:13:56 -0700 Subject: [PATCH] backport #484 to v2 --- token/program/Cargo.toml | 2 +- token/program/src/instruction.rs | 3 +- token/program/src/lib.rs | 2 - token/program/src/option.rs | 980 ------------------------------- token/program/src/pack.rs | 57 -- token/program/src/processor.rs | 4 +- token/program/src/state.rs | 15 +- 7 files changed, 12 insertions(+), 1051 deletions(-) delete mode 100644 token/program/src/option.rs delete mode 100644 token/program/src/pack.rs diff --git a/token/program/Cargo.toml b/token/program/Cargo.toml index 16e174f0..9be3b68b 100644 --- a/token/program/Cargo.toml +++ b/token/program/Cargo.toml @@ -21,7 +21,7 @@ default = ["solana-sdk/default"] num-derive = "0.3" num-traits = "0.2" remove_dir_all = "=0.5.0" -solana-sdk = { version = "1.3.11", default-features = false, optional = true } +solana-sdk = { version = "1.3.12", default-features = false, optional = true } thiserror = "1.0" arrayref = "0.3.6" num_enum = "0.5.1" diff --git a/token/program/src/instruction.rs b/token/program/src/instruction.rs index 5c8e1b00..ae01523e 100644 --- a/token/program/src/instruction.rs +++ b/token/program/src/instruction.rs @@ -1,9 +1,10 @@ //! Instruction types -use crate::{error::TokenError, option::COption}; +use crate::error::TokenError; use solana_sdk::{ instruction::{AccountMeta, Instruction}, program_error::ProgramError, + program_option::COption, pubkey::Pubkey, sysvar, }; diff --git a/token/program/src/lib.rs b/token/program/src/lib.rs index 52dc77f0..6e7108fe 100644 --- a/token/program/src/lib.rs +++ b/token/program/src/lib.rs @@ -7,8 +7,6 @@ pub mod entrypoint; pub mod error; pub mod instruction; pub mod native_mint; -pub mod option; -pub mod pack; pub mod processor; pub mod state; diff --git a/token/program/src/option.rs b/token/program/src/option.rs deleted file mode 100644 index 01ba5df8..00000000 --- a/token/program/src/option.rs +++ /dev/null @@ -1,980 +0,0 @@ -//! A C representation of Rust's `std::option::Option` used accross the FFI -//! boundary for Solana program interfaces -//! -//! This implementation mostly matches `std::option` except iterators since the iteration -//! trait requires returning `std::option::Option` - -use std::{ - convert, mem, - ops::{Deref, DerefMut}, -}; - -/// A C representation of Rust's `std::option::Option` -#[repr(C)] -#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -pub enum COption { - /// No value - None, - /// Some value `T` - Some(T), -} - -///////////////////////////////////////////////////////////////////////////// -// Type implementation -///////////////////////////////////////////////////////////////////////////// - -impl COption { - ///////////////////////////////////////////////////////////////////////// - // Querying the contained values - ///////////////////////////////////////////////////////////////////////// - - /// Returns `true` if the option is a [`COption::Some`] value. - /// - /// # Examples - /// - /// ```ignore - /// let x: COption = COption::Some(2); - /// assert_eq!(x.is_some(), true); - /// - /// let x: COption = COption::None; - /// assert_eq!(x.is_some(), false); - /// ``` - /// - /// [`COption::Some`]: #variant.COption::Some - #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] - #[inline] - pub fn is_some(&self) -> bool { - match *self { - COption::Some(_) => true, - COption::None => false, - } - } - - /// Returns `true` if the option is a [`COption::None`] value. - /// - /// # Examples - /// - /// ```ignore - /// let x: COption = COption::Some(2); - /// assert_eq!(x.is_none(), false); - /// - /// let x: COption = COption::None; - /// assert_eq!(x.is_none(), true); - /// ``` - /// - /// [`COption::None`]: #variant.COption::None - #[must_use = "if you intended to assert that this doesn't have a value, consider \ - `.and_then(|| panic!(\"`COption` had a value when expected `COption::None`\"))` instead"] - #[inline] - pub fn is_none(&self) -> bool { - !self.is_some() - } - - /// Returns `true` if the option is a [`COption::Some`] value containing the given value. - /// - /// # Examples - /// - /// ```ignore - /// #![feature(option_result_contains)] - /// - /// let x: COption = COption::Some(2); - /// assert_eq!(x.contains(&2), true); - /// - /// let x: COption = COption::Some(3); - /// assert_eq!(x.contains(&2), false); - /// - /// let x: COption = COption::None; - /// assert_eq!(x.contains(&2), false); - /// ``` - #[must_use] - #[inline] - pub fn contains(&self, x: &U) -> bool - where - U: PartialEq, - { - match self { - COption::Some(y) => x == y, - COption::None => false, - } - } - - ///////////////////////////////////////////////////////////////////////// - // Adapter for working with references - ///////////////////////////////////////////////////////////////////////// - - /// Converts from `&COption` to `COption<&T>`. - /// - /// # Examples - /// - /// Converts an `COption<`[`String`]`>` into an `COption<`[`usize`]`>`, preserving the original. - /// The [`map`] method takes the `self` argument by value, consuming the original, - /// so this technique uses `as_ref` to first take an `COption` to a reference - /// to the value inside the original. - /// - /// [`map`]: enum.COption.html#method.map - /// [`String`]: ../../std/string/struct.String.html - /// [`usize`]: ../../std/primitive.usize.html - /// - /// ```ignore - /// let text: COption = COption::Some("Hello, world!".to_string()); - /// // First, cast `COption` to `COption<&String>` with `as_ref`, - /// // then consume *that* with `map`, leaving `text` on the stack. - /// let text_length: COption = text.as_ref().map(|s| s.len()); - /// println!("still can print text: {:?}", text); - /// ``` - #[inline] - pub fn as_ref(&self) -> COption<&T> { - match *self { - COption::Some(ref x) => COption::Some(x), - COption::None => COption::None, - } - } - - /// Converts from `&mut COption` to `COption<&mut T>`. - /// - /// # Examples - /// - /// ```ignore - /// let mut x = COption::Some(2); - /// match x.as_mut() { - /// COption::Some(v) => *v = 42, - /// COption::None => {}, - /// } - /// assert_eq!(x, COption::Some(42)); - /// ``` - #[inline] - pub fn as_mut(&mut self) -> COption<&mut T> { - match *self { - COption::Some(ref mut x) => COption::Some(x), - COption::None => COption::None, - } - } - - ///////////////////////////////////////////////////////////////////////// - // Getting to contained values - ///////////////////////////////////////////////////////////////////////// - - /// Unwraps an option, yielding the content of a [`COption::Some`]. - /// - /// # Panics - /// - /// Panics if the value is a [`COption::None`] with a custom panic message provided by - /// `msg`. - /// - /// [`COption::Some`]: #variant.COption::Some - /// [`COption::None`]: #variant.COption::None - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some("value"); - /// assert_eq!(x.expect("the world is ending"), "value"); - /// ``` - /// - /// ```ignore{.should_panic} - /// let x: COption<&str> = COption::None; - /// x.expect("the world is ending"); // panics with `the world is ending` - /// ``` - #[inline] - pub fn expect(self, msg: &str) -> T { - match self { - COption::Some(val) => val, - COption::None => expect_failed(msg), - } - } - - /// Moves the value `v` out of the `COption` if it is [`COption::Some(v)`]. - /// - /// In general, because this function may panic, its use is discouraged. - /// Instead, prefer to use pattern matching and handle the [`COption::None`] - /// case explicitly. - /// - /// # Panics - /// - /// Panics if the self value equals [`COption::None`]. - /// - /// [`COption::Some(v)`]: #variant.COption::Some - /// [`COption::None`]: #variant.COption::None - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some("air"); - /// assert_eq!(x.unwrap(), "air"); - /// ``` - /// - /// ```ignore{.should_panic} - /// let x: COption<&str> = COption::None; - /// assert_eq!(x.unwrap(), "air"); // fails - /// ``` - #[inline] - pub fn unwrap(self) -> T { - match self { - COption::Some(val) => val, - COption::None => panic!("called `COption::unwrap()` on a `COption::None` value"), - } - } - - /// Returns the contained value or a default. - /// - /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing - /// the result of a function call, it is recommended to use [`unwrap_or_else`], - /// which is lazily evaluated. - /// - /// [`unwrap_or_else`]: #method.unwrap_or_else - /// - /// # Examples - /// - /// ```ignore - /// assert_eq!(COption::Some("car").unwrap_or("bike"), "car"); - /// assert_eq!(COption::None.unwrap_or("bike"), "bike"); - /// ``` - #[inline] - pub fn unwrap_or(self, def: T) -> T { - match self { - COption::Some(x) => x, - COption::None => def, - } - } - - /// Returns the contained value or computes it from a closure. - /// - /// # Examples - /// - /// ```ignore - /// let k = 10; - /// assert_eq!(COption::Some(4).unwrap_or_else(|| 2 * k), 4); - /// assert_eq!(COption::None.unwrap_or_else(|| 2 * k), 20); - /// ``` - #[inline] - pub fn unwrap_or_else T>(self, f: F) -> T { - match self { - COption::Some(x) => x, - COption::None => f(), - } - } - - ///////////////////////////////////////////////////////////////////////// - // Transforming contained values - ///////////////////////////////////////////////////////////////////////// - - /// Maps an `COption` to `COption` by applying a function to a contained value. - /// - /// # Examples - /// - /// Converts an `COption<`[`String`]`>` into an `COption<`[`usize`]`>`, consuming the original: - /// - /// [`String`]: ../../std/string/struct.String.html - /// [`usize`]: ../../std/primitive.usize.html - /// - /// ```ignore - /// let maybe_some_string = COption::Some(String::from("Hello, World!")); - /// // `COption::map` takes self *by value*, consuming `maybe_some_string` - /// let maybe_some_len = maybe_some_string.map(|s| s.len()); - /// - /// assert_eq!(maybe_some_len, COption::Some(13)); - /// ``` - #[inline] - pub fn map U>(self, f: F) -> COption { - match self { - COption::Some(x) => COption::Some(f(x)), - COption::None => COption::None, - } - } - - /// Applies a function to the contained value (if any), - /// or returns the provided default (if not). - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some("foo"); - /// assert_eq!(x.map_or(42, |v| v.len()), 3); - /// - /// let x: COption<&str> = COption::None; - /// assert_eq!(x.map_or(42, |v| v.len()), 42); - /// ``` - #[inline] - pub fn map_or U>(self, default: U, f: F) -> U { - match self { - COption::Some(t) => f(t), - COption::None => default, - } - } - - /// Applies a function to the contained value (if any), - /// or computes a default (if not). - /// - /// # Examples - /// - /// ```ignore - /// let k = 21; - /// - /// let x = COption::Some("foo"); - /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3); - /// - /// let x: COption<&str> = COption::None; - /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42); - /// ``` - #[inline] - pub fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { - match self { - COption::Some(t) => f(t), - COption::None => default(), - } - } - - /// Transforms the `COption` into a [`Result`], mapping [`COption::Some(v)`] to - /// [`Ok(v)`] and [`COption::None`] to [`Err(err)`]. - /// - /// Arguments passed to `ok_or` are eagerly evaluated; if you are passing the - /// result of a function call, it is recommended to use [`ok_or_else`], which is - /// lazily evaluated. - /// - /// [`Result`]: ../../std/result/enum.Result.html - /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok - /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err - /// [`COption::None`]: #variant.COption::None - /// [`COption::Some(v)`]: #variant.COption::Some - /// [`ok_or_else`]: #method.ok_or_else - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some("foo"); - /// assert_eq!(x.ok_or(0), Ok("foo")); - /// - /// let x: COption<&str> = COption::None; - /// assert_eq!(x.ok_or(0), Err(0)); - /// ``` - #[inline] - pub fn ok_or(self, err: E) -> Result { - match self { - COption::Some(v) => Ok(v), - COption::None => Err(err), - } - } - - /// Transforms the `COption` into a [`Result`], mapping [`COption::Some(v)`] to - /// [`Ok(v)`] and [`COption::None`] to [`Err(err())`]. - /// - /// [`Result`]: ../../std/result/enum.Result.html - /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok - /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err - /// [`COption::None`]: #variant.COption::None - /// [`COption::Some(v)`]: #variant.COption::Some - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some("foo"); - /// assert_eq!(x.ok_or_else(|| 0), Ok("foo")); - /// - /// let x: COption<&str> = COption::None; - /// assert_eq!(x.ok_or_else(|| 0), Err(0)); - /// ``` - #[inline] - pub fn ok_or_else E>(self, err: F) -> Result { - match self { - COption::Some(v) => Ok(v), - COption::None => Err(err()), - } - } - - ///////////////////////////////////////////////////////////////////////// - // Boolean operations on the values, eager and lazy - ///////////////////////////////////////////////////////////////////////// - - /// Returns [`COption::None`] if the option is [`COption::None`], otherwise returns `optb`. - /// - /// [`COption::None`]: #variant.COption::None - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some(2); - /// let y: COption<&str> = COption::None; - /// assert_eq!(x.and(y), COption::None); - /// - /// let x: COption = COption::None; - /// let y = COption::Some("foo"); - /// assert_eq!(x.and(y), COption::None); - /// - /// let x = COption::Some(2); - /// let y = COption::Some("foo"); - /// assert_eq!(x.and(y), COption::Some("foo")); - /// - /// let x: COption = COption::None; - /// let y: COption<&str> = COption::None; - /// assert_eq!(x.and(y), COption::None); - /// ``` - #[inline] - pub fn and(self, optb: COption) -> COption { - match self { - COption::Some(_) => optb, - COption::None => COption::None, - } - } - - /// Returns [`COption::None`] if the option is [`COption::None`], otherwise calls `f` with the - /// wrapped value and returns the result. - /// - /// COption::Some languages call this operation flatmap. - /// - /// [`COption::None`]: #variant.COption::None - /// - /// # Examples - /// - /// ```ignore - /// fn sq(x: u32) -> COption { COption::Some(x * x) } - /// fn nope(_: u32) -> COption { COption::None } - /// - /// assert_eq!(COption::Some(2).and_then(sq).and_then(sq), COption::Some(16)); - /// assert_eq!(COption::Some(2).and_then(sq).and_then(nope), COption::None); - /// assert_eq!(COption::Some(2).and_then(nope).and_then(sq), COption::None); - /// assert_eq!(COption::None.and_then(sq).and_then(sq), COption::None); - /// ``` - #[inline] - pub fn and_then COption>(self, f: F) -> COption { - match self { - COption::Some(x) => f(x), - COption::None => COption::None, - } - } - - /// Returns [`COption::None`] if the option is [`COption::None`], otherwise calls `predicate` - /// with the wrapped value and returns: - /// - /// - [`COption::Some(t)`] if `predicate` returns `true` (where `t` is the wrapped - /// value), and - /// - [`COption::None`] if `predicate` returns `false`. - /// - /// This function works similar to [`Iterator::filter()`]. You can imagine - /// the `COption` being an iterator over one or zero elements. `filter()` - /// lets you decide which elements to keep. - /// - /// # Examples - /// - /// ```ignore - /// fn is_even(n: &i32) -> bool { - /// n % 2 == 0 - /// } - /// - /// assert_eq!(COption::None.filter(is_even), COption::None); - /// assert_eq!(COption::Some(3).filter(is_even), COption::None); - /// assert_eq!(COption::Some(4).filter(is_even), COption::Some(4)); - /// ``` - /// - /// [`COption::None`]: #variant.COption::None - /// [`COption::Some(t)`]: #variant.COption::Some - /// [`Iterator::filter()`]: ../../std/iter/trait.Iterator.html#method.filter - #[inline] - pub fn filter bool>(self, predicate: P) -> Self { - if let COption::Some(x) = self { - if predicate(&x) { - return COption::Some(x); - } - } - COption::None - } - - /// Returns the option if it contains a value, otherwise returns `optb`. - /// - /// Arguments passed to `or` are eagerly evaluated; if you are passing the - /// result of a function call, it is recommended to use [`or_else`], which is - /// lazily evaluated. - /// - /// [`or_else`]: #method.or_else - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some(2); - /// let y = COption::None; - /// assert_eq!(x.or(y), COption::Some(2)); - /// - /// let x = COption::None; - /// let y = COption::Some(100); - /// assert_eq!(x.or(y), COption::Some(100)); - /// - /// let x = COption::Some(2); - /// let y = COption::Some(100); - /// assert_eq!(x.or(y), COption::Some(2)); - /// - /// let x: COption = COption::None; - /// let y = COption::None; - /// assert_eq!(x.or(y), COption::None); - /// ``` - #[inline] - pub fn or(self, optb: COption) -> COption { - match self { - COption::Some(_) => self, - COption::None => optb, - } - } - - /// Returns the option if it contains a value, otherwise calls `f` and - /// returns the result. - /// - /// # Examples - /// - /// ```ignore - /// fn nobody() -> COption<&'static str> { COption::None } - /// fn vikings() -> COption<&'static str> { COption::Some("vikings") } - /// - /// assert_eq!(COption::Some("barbarians").or_else(vikings), COption::Some("barbarians")); - /// assert_eq!(COption::None.or_else(vikings), COption::Some("vikings")); - /// assert_eq!(COption::None.or_else(nobody), COption::None); - /// ``` - #[inline] - pub fn or_else COption>(self, f: F) -> COption { - match self { - COption::Some(_) => self, - COption::None => f(), - } - } - - /// Returns [`COption::Some`] if exactly one of `self`, `optb` is [`COption::Some`], otherwise returns [`COption::None`]. - /// - /// [`COption::Some`]: #variant.COption::Some - /// [`COption::None`]: #variant.COption::None - /// - /// # Examples - /// - /// ```ignore - /// let x = COption::Some(2); - /// let y: COption = COption::None; - /// assert_eq!(x.xor(y), COption::Some(2)); - /// - /// let x: COption = COption::None; - /// let y = COption::Some(2); - /// assert_eq!(x.xor(y), COption::Some(2)); - /// - /// let x = COption::Some(2); - /// let y = COption::Some(2); - /// assert_eq!(x.xor(y), COption::None); - /// - /// let x: COption = COption::None; - /// let y: COption = COption::None; - /// assert_eq!(x.xor(y), COption::None); - /// ``` - #[inline] - pub fn xor(self, optb: COption) -> COption { - match (self, optb) { - (COption::Some(a), COption::None) => COption::Some(a), - (COption::None, COption::Some(b)) => COption::Some(b), - _ => COption::None, - } - } - - ///////////////////////////////////////////////////////////////////////// - // Entry-like operations to insert if COption::None and return a reference - ///////////////////////////////////////////////////////////////////////// - - /// Inserts `v` into the option if it is [`COption::None`], then - /// returns a mutable reference to the contained value. - /// - /// [`COption::None`]: #variant.COption::None - /// - /// # Examples - /// - /// ```ignore - /// let mut x = COption::None; - /// - /// { - /// let y: &mut u32 = x.get_or_insert(5); - /// assert_eq!(y, &5); - /// - /// *y = 7; - /// } - /// - /// assert_eq!(x, COption::Some(7)); - /// ``` - #[inline] - pub fn get_or_insert(&mut self, v: T) -> &mut T { - self.get_or_insert_with(|| v) - } - - /// Inserts a value computed from `f` into the option if it is [`COption::None`], then - /// returns a mutable reference to the contained value. - /// - /// [`COption::None`]: #variant.COption::None - /// - /// # Examples - /// - /// ```ignore - /// let mut x = COption::None; - /// - /// { - /// let y: &mut u32 = x.get_or_insert_with(|| 5); - /// assert_eq!(y, &5); - /// - /// *y = 7; - /// } - /// - /// assert_eq!(x, COption::Some(7)); - /// ``` - #[inline] - pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { - if let COption::None = *self { - *self = COption::Some(f()) - } - - match *self { - COption::Some(ref mut v) => v, - COption::None => unreachable!(), - } - } - - ///////////////////////////////////////////////////////////////////////// - // Misc - ///////////////////////////////////////////////////////////////////////// - - /// Replaces the actual value in the option by the value given in parameter, - /// returning the old value if present, - /// leaving a [`COption::Some`] in its place without deinitializing either one. - /// - /// [`COption::Some`]: #variant.COption::Some - /// - /// # Examples - /// - /// ```ignore - /// let mut x = COption::Some(2); - /// let old = x.replace(5); - /// assert_eq!(x, COption::Some(5)); - /// assert_eq!(old, COption::Some(2)); - /// - /// let mut x = COption::None; - /// let old = x.replace(3); - /// assert_eq!(x, COption::Some(3)); - /// assert_eq!(old, COption::None); - /// ``` - #[inline] - pub fn replace(&mut self, value: T) -> COption { - mem::replace(self, COption::Some(value)) - } -} - -impl COption<&T> { - /// Maps an `COption<&T>` to an `COption` by copying the contents of the - /// option. - /// - /// # Examples - /// - /// ```ignore - /// let x = 12; - /// let opt_x = COption::Some(&x); - /// assert_eq!(opt_x, COption::Some(&12)); - /// let copied = opt_x.copied(); - /// assert_eq!(copied, COption::Some(12)); - /// ``` - pub fn copied(self) -> COption { - self.map(|&t| t) - } -} - -impl COption<&mut T> { - /// Maps an `COption<&mut T>` to an `COption` by copying the contents of the - /// option. - /// - /// # Examples - /// - /// ```ignore - /// let mut x = 12; - /// let opt_x = COption::Some(&mut x); - /// assert_eq!(opt_x, COption::Some(&mut 12)); - /// let copied = opt_x.copied(); - /// assert_eq!(copied, COption::Some(12)); - /// ``` - pub fn copied(self) -> COption { - self.map(|&mut t| t) - } -} - -impl COption<&T> { - /// Maps an `COption<&T>` to an `COption` by cloning the contents of the - /// option. - /// - /// # Examples - /// - /// ```ignore - /// let x = 12; - /// let opt_x = COption::Some(&x); - /// assert_eq!(opt_x, COption::Some(&12)); - /// let cloned = opt_x.cloned(); - /// assert_eq!(cloned, COption::Some(12)); - /// ``` - pub fn cloned(self) -> COption { - self.map(|t| t.clone()) - } -} - -impl COption<&mut T> { - /// Maps an `COption<&mut T>` to an `COption` by cloning the contents of the - /// option. - /// - /// # Examples - /// - /// ```ignore - /// let mut x = 12; - /// let opt_x = COption::Some(&mut x); - /// assert_eq!(opt_x, COption::Some(&mut 12)); - /// let cloned = opt_x.cloned(); - /// assert_eq!(cloned, COption::Some(12)); - /// ``` - pub fn cloned(self) -> COption { - self.map(|t| t.clone()) - } -} - -impl COption { - /// Returns the contained value or a default - /// - /// Consumes the `self` argument then, if [`COption::Some`], returns the contained - /// value, otherwise if [`COption::None`], returns the [default value] for that - /// type. - /// - /// # Examples - /// - /// Converts a string to an integer, turning poorly-formed strings - /// into 0 (the default value for integers). [`parse`] converts - /// a string to any other type that implements [`FromStr`], returning - /// [`COption::None`] on error. - /// - /// ```ignore - /// let good_year_from_input = "1909"; - /// let bad_year_from_input = "190blarg"; - /// let good_year = good_year_from_input.parse().ok().unwrap_or_default(); - /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default(); - /// - /// assert_eq!(1909, good_year); - /// assert_eq!(0, bad_year); - /// ``` - /// - /// [`COption::Some`]: #variant.COption::Some - /// [`COption::None`]: #variant.COption::None - /// [default value]: ../default/trait.Default.html#tymethod.default - /// [`parse`]: ../../std/primitive.str.html#method.parse - /// [`FromStr`]: ../../std/str/trait.FromStr.html - #[inline] - pub fn unwrap_or_default(self) -> T { - match self { - COption::Some(x) => x, - COption::None => Default::default(), - } - } -} - -impl COption { - /// Converts from `COption` (or `&COption`) to `COption<&T::Target>`. - /// - /// Leaves the original COption in-place, creating a new one with a reference - /// to the original one, additionally coercing the contents via [`Deref`]. - /// - /// [`Deref`]: ../../std/ops/trait.Deref.html - /// - /// # Examples - /// - /// ```ignore - /// #![feature(inner_deref)] - /// - /// let x: COption = COption::Some("hey".to_owned()); - /// assert_eq!(x.as_deref(), COption::Some("hey")); - /// - /// let x: COption = COption::None; - /// assert_eq!(x.as_deref(), COption::None); - /// ``` - pub fn as_deref(&self) -> COption<&T::Target> { - self.as_ref().map(|t| t.deref()) - } -} - -impl COption { - /// Converts from `COption` (or `&mut COption`) to `COption<&mut T::Target>`. - /// - /// Leaves the original `COption` in-place, creating a new one containing a mutable reference to - /// the inner type's `Deref::Target` type. - /// - /// # Examples - /// - /// ```ignore - /// #![feature(inner_deref)] - /// - /// let mut x: COption = COption::Some("hey".to_owned()); - /// assert_eq!(x.as_deref_mut().map(|x| { - /// x.make_ascii_uppercase(); - /// x - /// }), COption::Some("HEY".to_owned().as_mut_str())); - /// ``` - pub fn as_deref_mut(&mut self) -> COption<&mut T::Target> { - self.as_mut().map(|t| t.deref_mut()) - } -} - -impl COption> { - /// Transposes an `COption` of a [`Result`] into a [`Result`] of an `COption`. - /// - /// [`COption::None`] will be mapped to [`Ok`]`(`[`COption::None`]`)`. - /// [`COption::Some`]`(`[`Ok`]`(_))` and [`COption::Some`]`(`[`Err`]`(_))` will be mapped to - /// [`Ok`]`(`[`COption::Some`]`(_))` and [`Err`]`(_)`. - /// - /// [`COption::None`]: #variant.COption::None - /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok - /// [`COption::Some`]: #variant.COption::Some - /// [`Err`]: ../../std/result/enum.Result.html#variant.Err - /// - /// # Examples - /// - /// ```ignore - /// #[derive(Debug, Eq, PartialEq)] - /// struct COption::SomeErr; - /// - /// let x: Result, COption::SomeErr> = Ok(COption::Some(5)); - /// let y: COption> = COption::Some(Ok(5)); - /// assert_eq!(x, y.transpose()); - /// ``` - #[inline] - pub fn transpose(self) -> Result, E> { - match self { - COption::Some(Ok(x)) => Ok(COption::Some(x)), - COption::Some(Err(e)) => Err(e), - COption::None => Ok(COption::None), - } - } -} - -// This is a separate function to reduce the code size of .expect() itself. -#[inline(never)] -#[cold] -fn expect_failed(msg: &str) -> ! { - panic!("{}", msg) -} - -// // This is a separate function to reduce the code size of .expect_none() itself. -// #[inline(never)] -// #[cold] -// fn expect_none_failed(msg: &str, value: &dyn fmt::Debug) -> ! { -// panic!("{}: {:?}", msg, value) -// } - -///////////////////////////////////////////////////////////////////////////// -// Trait implementations -///////////////////////////////////////////////////////////////////////////// - -impl Clone for COption { - #[inline] - fn clone(&self) -> Self { - match self { - COption::Some(x) => COption::Some(x.clone()), - COption::None => COption::None, - } - } - - #[inline] - fn clone_from(&mut self, source: &Self) { - match (self, source) { - (COption::Some(to), COption::Some(from)) => to.clone_from(from), - (to, from) => *to = from.clone(), - } - } -} - -impl Default for COption { - /// Returns [`COption::None`][COption::COption::None]. - /// - /// # Examples - /// - /// ```ignore - /// let opt: COption = COption::default(); - /// assert!(opt.is_none()); - /// ``` - #[inline] - fn default() -> COption { - COption::None - } -} - -impl From for COption { - fn from(val: T) -> COption { - COption::Some(val) - } -} - -impl<'a, T> From<&'a COption> for COption<&'a T> { - fn from(o: &'a COption) -> COption<&'a T> { - o.as_ref() - } -} - -impl<'a, T> From<&'a mut COption> for COption<&'a mut T> { - fn from(o: &'a mut COption) -> COption<&'a mut T> { - o.as_mut() - } -} - -impl COption> { - /// Converts from `COption>` to `COption` - /// - /// # Examples - /// Basic usage: - /// ```ignore - /// #![feature(option_flattening)] - /// let x: COption> = COption::Some(COption::Some(6)); - /// assert_eq!(COption::Some(6), x.flatten()); - /// - /// let x: COption> = COption::Some(COption::None); - /// assert_eq!(COption::None, x.flatten()); - /// - /// let x: COption> = COption::None; - /// assert_eq!(COption::None, x.flatten()); - /// ``` - /// Flattening once only removes one level of nesting: - /// ```ignore - /// #![feature(option_flattening)] - /// let x: COption>> = COption::Some(COption::Some(COption::Some(6))); - /// assert_eq!(COption::Some(COption::Some(6)), x.flatten()); - /// assert_eq!(COption::Some(6), x.flatten().flatten()); - /// ``` - #[inline] - pub fn flatten(self) -> COption { - self.and_then(convert::identity) - } -} - -impl From> for COption { - fn from(option: Option) -> Self { - match option { - Some(value) => COption::Some(value), - None => COption::None, - } - } -} - -impl Into> for COption { - fn into(self) -> Option { - match self { - COption::Some(value) => Some(value), - COption::None => None, - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_from_rust_option() { - let option = Some(99u64); - let c_option: COption = option.into(); - assert_eq!(c_option, COption::Some(99u64)); - let expected = c_option.into(); - assert_eq!(option, expected); - - let option = None; - let c_option: COption = option.into(); - assert_eq!(c_option, COption::None); - let expected = c_option.into(); - assert_eq!(option, expected); - } -} diff --git a/token/program/src/pack.rs b/token/program/src/pack.rs deleted file mode 100644 index 7c0f3550..00000000 --- a/token/program/src/pack.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! State transition types - -use solana_sdk::program_error::ProgramError; - -/// Check is a token state is initialized -pub trait IsInitialized { - /// Is initialized - fn is_initialized(&self) -> bool; -} - -/// Depends on Sized -pub trait Sealed: Sized {} - -/// Safely and efficiently (de)serialize account state -pub trait Pack: Sealed { - /// The length, in bytes, of the packed representation - const LEN: usize; - #[doc(hidden)] - fn pack_into_slice(&self, dst: &mut [u8]); - #[doc(hidden)] - fn unpack_from_slice(src: &[u8]) -> Result; - - /// Get the packed length - fn get_packed_len() -> usize { - Self::LEN - } - - /// Unpack from slice and check if initialized - fn unpack(input: &[u8]) -> Result - where - Self: IsInitialized, - { - let value = Self::unpack_unchecked(input)?; - if value.is_initialized() { - Ok(value) - } else { - Err(ProgramError::UninitializedAccount) - } - } - - /// Unpack from slice without checking if initialized - fn unpack_unchecked(input: &[u8]) -> Result { - if input.len() != Self::LEN { - return Err(ProgramError::InvalidAccountData); - } - Ok(Self::unpack_from_slice(input)?) - } - - /// Pack into slice - fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError> { - if dst.len() != Self::LEN { - return Err(ProgramError::InvalidAccountData); - } - src.pack_into_slice(dst); - Ok(()) - } -} diff --git a/token/program/src/processor.rs b/token/program/src/processor.rs index a4ce7a09..4ab5727e 100644 --- a/token/program/src/processor.rs +++ b/token/program/src/processor.rs @@ -5,8 +5,6 @@ use crate::{ error::TokenError, instruction::{is_valid_signer_index, AuthorityType, TokenInstruction, MAX_SIGNERS}, - option::COption, - pack::{IsInitialized, Pack}, state::{Account, AccountState, Mint, Multisig}, }; use num_traits::FromPrimitive; @@ -16,6 +14,8 @@ use solana_sdk::{ entrypoint::ProgramResult, info, program_error::{PrintProgramError, ProgramError}, + program_option::COption, + program_pack::{IsInitialized, Pack}, pubkey::Pubkey, sysvar::{rent::Rent, Sysvar}, }; diff --git a/token/program/src/state.rs b/token/program/src/state.rs index 5d14af7c..3622471e 100644 --- a/token/program/src/state.rs +++ b/token/program/src/state.rs @@ -1,15 +1,14 @@ //! State transition types -use crate::{ - instruction::MAX_SIGNERS, - option::COption, - pack::{IsInitialized, Pack, Sealed}, -}; +use crate::instruction::MAX_SIGNERS; use arrayref::{array_mut_ref, array_ref, array_refs, mut_array_refs}; use num_enum::TryFromPrimitive; -use solana_sdk::{program_error::ProgramError, pubkey::Pubkey}; - -impl Sealed for Option {} +use solana_sdk::{ + program_error::ProgramError, + program_option::COption, + program_pack::{IsInitialized, Pack, Sealed}, + pubkey::Pubkey, +}; /// Mint data. #[repr(C)]