Repository: meilisearch/meilisearch
File: meilisearch-auth/src/store.rs (Rust)

Code before:
        let action = Action::from_repr(u8::from_be_bytes(*action_bytes))?;

        Some((key_id, action, index))
    }
}

impl<'a> milli::heed::BytesEncode<'a> for KeyIdActionCodec {
    type EItem = (&'a KeyId, &'a Action, Option<&'a [u8]>);

    fn bytes_encode((key_id, action, index): &Self::EItem) -> Option<Cow<[u8]>> {
        let mut bytes = Vec::new();

        bytes.extend_from_slice(key_id.as_bytes());
        let action_bytes = u8::to_be_bytes(action.repr());
        bytes.extend_from_slice(&action_bytes);
        if let Some(index) = index {
            bytes.extend_from_slice(index);
        }

        Some(Cow::Owned(bytes))
    }
}

pub fn generate_key_as_base64(uid: &[u8], master_key: &[u8]) -> String {
    let master_key_sha = Sha256::digest(master_key);
    let mut mac = Hmac::<Sha256>::new_from_slice(master_key).unwrap();
    mac.update(uid);

    let result = mac.finalize();
    base64::encode_config(result.into_bytes(), base64::URL_SAFE_NO_PAD)
}

/// Divides one slice into two at an index, returns `None` if mid is out of bounds.
pub fn try_split_at<T>(slice: &[T], mid: usize) -> Option<(&[T], &[T])> {
    if mid <= slice.len() {
        Some(slice.split_at(mid))
    } else {
        None
    }
}

/// Divides one slice into an array and the tail at an index,
/// returns `None` if `N` is out of bounds.
pub fn try_split_array_at<T, const N: usize>(slice: &[T]) -> Option<(&[T; N], &[T])>
where
    [T; N]: for<'a> TryFrom<&'a [T]>,
{
    let (head, tail) = try_split_at(slice, N)?;
    let head = head.try_into().ok()?;
    Some((head, tail))
}

Review comment (suggestion):
this can be unwrapped safely because `Hmac::new_from_slice` never returns an error:
https://docs.rs/hmac/0.12.1/src/hmac/optim.rs.html#152-174

Code after:
        let action = Action::from_repr(u8::from_be_bytes(*action_bytes))?;

        Some((key_id, action, index))
    }
}

impl<'a> milli::heed::BytesEncode<'a> for KeyIdActionCodec {
    type EItem = (&'a KeyId, &'a Action, Option<&'a [u8]>);

    fn bytes_encode((key_id, action, index): &Self::EItem) -> Option<Cow<[u8]>> {
        let mut bytes = Vec::new();

        bytes.extend_from_slice(key_id.as_bytes());
        let action_bytes = u8::to_be_bytes(action.repr());
        bytes.extend_from_slice(&action_bytes);
        if let Some(index) = index {
            bytes.extend_from_slice(index);
        }

        Some(Cow::Owned(bytes))
    }
}

pub fn generate_key_as_base64(uid: &[u8], master_key: &[u8]) -> String {
    let master_key_sha = Sha256::digest(master_key);
    let mut mac = Hmac::<Sha256>::new_from_slice(master_key_sha.as_slice()).unwrap();
    mac.update(uid);

    let result = mac.finalize();
    base64::encode_config(result.into_bytes(), base64::URL_SAFE_NO_PAD)
}

/// Divides one slice into two at an index, returns `None` if mid is out of bounds.
pub fn try_split_at<T>(slice: &[T], mid: usize) -> Option<(&[T], &[T])> {
    if mid <= slice.len() {
        Some(slice.split_at(mid))
    } else {
        None
    }
}

/// Divides one slice into an array and the tail at an index,
/// returns `None` if `N` is out of bounds.
pub fn try_split_array_at<T, const N: usize>(slice: &[T]) -> Option<(&[T; N], &[T])>
where
    [T; N]: for<'a> TryFrom<&'a [T]>,
{
    let (head, tail) = try_split_at(slice, N)?;
    let head = head.try_into().ok()?;
    Some((head, tail))
}