Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify implementing newtype Map key types #43

Open
uint opened this issue Jun 12, 2024 · 2 comments
Open

Simplify implementing newtype Map key types #43

uint opened this issue Jun 12, 2024 · 2 comments
Labels
good first issue Good for newcomers help wanted Extra attention is needed
Milestone

Comments

@uint
Copy link
Collaborator

uint commented Jun 12, 2024

@dakom raised this. Sometimes you want to use something with more meaning than String (or w/e), and newtype is the right option.

Let's make sure it's not overly complicated to implement all the right traits (OwnedKey, Key, std::borrow::Borrow). Maybe a derive macro is in order.

@uint uint added this to the v0.4.0 milestone Sep 4, 2024
@uint uint added good first issue Good for newcomers help wanted Extra attention is needed labels Sep 18, 2024
@dakom
Copy link

dakom commented Sep 24, 2024

FYI here's an example from storage-plus... not sure if all of this is necessary, copy/pasted from somewhere

use cosmwasm_schema::cw_serde;
use cosmwasm_std::{StdResult, Uint64};
use cw_storage_plus::{IntKey, Key, KeyDeserialize, Prefixer, PrimaryKey};
use std::{hash::Hash, num::ParseIntError, str::FromStr};

/// An id for a task. This is a simple wrapper around a `Uint64` internally.
/// Serialized on the wire as a string
#[cw_serde]
#[derive(Copy, PartialOrd, Ord, Eq)]
pub struct TaskId(Uint64);

impl Hash for TaskId {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.u64().hash(state);
    }
}

impl TaskId {
    /// Construct a new value from a [u64].
    pub fn new(x: u64) -> Self {
        Self(x.into())
    }

    /// The underlying `u64` representation.
    pub fn u64(self) -> u64 {
        self.0.u64()
    }
}

impl<'a> PrimaryKey<'a> for TaskId {
    type Prefix = ();
    type SubPrefix = ();
    type Suffix = Self;
    type SuperSuffix = Self;

    fn key(&self) -> Vec<Key> {
        vec![Key::Val64(self.0.u64().to_cw_bytes())]
    }
}

impl<'a> Prefixer<'a> for TaskId {
    fn prefix(&self) -> Vec<Key> {
        vec![Key::Val64(self.0.u64().to_cw_bytes())]
    }
}

impl KeyDeserialize for TaskId {
    type Output = TaskId;

    #[inline(always)]
    fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
        u64::from_vec(value).map(|x| TaskId(Uint64::new(x)))
    }
}

impl std::fmt::Display for TaskId {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl FromStr for TaskId {
    type Err = ParseIntError;
    fn from_str(src: &str) -> Result<Self, ParseIntError> {
        src.parse().map(|x| TaskId(Uint64::new(x)))
    }
}

@dakom
Copy link

dakom commented Sep 25, 2024

opened a PR for a derive macro on cw-storage-plus that might be a better starting point: CosmWasm/cw-storage-plus#88

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants