Repository: awslabs/llrt
File: llrt_core/src/modules/llrt/uuid.rs (Rust)

Code before:
        .format_hyphenated()
        .to_string();
    Ok(uuid)
}

pub fn uuidv4() -> String {
    Uuid::new_v4().format_hyphenated().to_string()
}

fn parse(ctx: Ctx<'_>, value: String) -> Result<TypedArray<u8>> {
    let uuid = Uuid::try_parse(&value).or_throw_msg(&ctx, ERROR_MESSAGE)?;
    let bytes = uuid.as_bytes();
    TypedArray::<u8>::new(ctx, *bytes)
}

fn stringify<'js>(ctx: Ctx<'js>, value: Value<'js>, offset: Opt<u8>) -> Result<String> {
    let value = get_bytes_offset_length(
        &ctx,
        value,
        offset.0.map(|o| o.into()).unwrap_or_default(),
        None,
    )?;
    let value = bytes_to_hex(&value);

    let uuid = Uuid::try_parse_ascii(&value)
        .or_throw_msg(&ctx, ERROR_MESSAGE)?
        .as_hyphenated()
        .to_string();

    Ok(uuid)
}

fn validate(value: String) -> bool {
    Uuid::parse_str(&value).is_ok()
}

fn version(ctx: Ctx<'_>, value: String) -> Result<u8> {
    let uuid = Uuid::parse_str(&value).or_throw_msg(&ctx, ERROR_MESSAGE)?;
    Ok(uuid.get_version().map(|v| v as u8).unwrap_or(0))
}

impl ModuleDef for LlrtUuidModule {
    fn declare(declare: &Declarations) -> Result<()> {
        declare.declare("v1")?;
        declare.declare("v3")?;
        declare.declare("v4")?;
        declare.declare("v5")?;
        declare.declare("parse")?;
        declare.declare("validate")?;
        declare.declare("stringify")?;
        declare.declare("version")?;

Review comment (suggestion):
Note: the Node.js package implementation does `((v1_bytes[7] >> 4) & 0x0f)` instead for getting the upper 4 bits of the 7th byte, which is used to set the lower 4 bits of the 0th byte of the uuidv6.

_I think_ there's no differences, plus the rest of the lines does not do that.

I made a comment on their PR to ask about this: https://github.com/uuidjs/uuid/pull/754#discussion_r1703097117

Code after:
fn uuidv5<'js>(ctx: Ctx<'js>, name: String, namespace: Value<'js>) -> Result<String> {
    let uuid = Uuid::new_v5(&from_value(&ctx, namespace)?, name.as_bytes())
        .format_hyphenated()
        .to_string();
    Ok(uuid)
}

pub fn uuidv4() -> String {
    Uuid::new_v4().format_hyphenated().to_string()
}

fn uuidv6() -> String {
    Uuid::now_v6(&NODE_ID).format_hyphenated().to_string()
}

fn uuidv7() -> String {
    Uuid::now_v7().format_hyphenated().to_string()
}

fn uuidv1_to_v6<'js>(ctx: Ctx<'js>, v1_value: Value<'js>) -> Result<String> {
    let v1_uuid = from_value(&ctx, v1_value)?;
    let v1_bytes = v1_uuid.as_bytes();
    let mut v6_bytes = [0u8; 16];

    // time_high
    v6_bytes[0] = ((v1_bytes[6] & 0x0f) << 4) | ((v1_bytes[7] & 0xf0) >> 4);
    v6_bytes[1] = ((v1_bytes[7] & 0x0f) << 4) | ((v1_bytes[4] & 0xf0) >> 4);
    v6_bytes[2] = ((v1_bytes[4] & 0x0f) << 4) | ((v1_bytes[5] & 0xf0) >> 4);
    v6_bytes[3] = ((v1_bytes[5] & 0x0f) << 4) | ((v1_bytes[0] & 0xf0) >> 4);

    // time_mid
    v6_bytes[4] = ((v1_bytes[0] & 0x0f) << 4) | ((v1_bytes[1] & 0xf0) >> 4);
    v6_bytes[5] = ((v1_bytes[1] & 0x0f) << 4) | ((v1_bytes[2] & 0xf0) >> 4);

    // version and time_low
    v6_bytes[6] = 0x60 | (v1_bytes[2] & 0x0f);
    v6_bytes[7] = v1_bytes[3];

    // clock_seq and node
    v6_bytes[8..16].copy_from_slice(&v1_bytes[8..16]);

    Ok(Uuid::from_bytes(v6_bytes).format_hyphenated().to_string())
}

fn uuidv6_to_v1<'js>(ctx: Ctx<'js>, v6_value: Value<'js>) -> Result<String> {
    let v6_uuid = from_value(&ctx, v6_value)?;
    let v6_bytes: &[u8; 16] = v6_uuid.as_bytes();
    let mut v1_bytes = [0u8; 16];

    // time_low
    v1_bytes[0] = (v6_bytes[3] & 0x0f) << 4 | (v6_bytes[4] & 0xf0) >> 4;