Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d69fc851 authored by Martin Geisler's avatar Martin Geisler
Browse files

pdl: Move get_uint and put_uint to common module

We will need access to both of them from the parser next.

Test: atest pdl_tests pdl_rust_generator_tests_{le,be}
Change-Id: I7cfd79f2ef811765cd7b3653b8ed1b0ddb14fc70
parent 3b45db5b
Loading
Loading
Loading
Loading
+1 −32
Original line number Diff line number Diff line
@@ -38,37 +38,6 @@ impl<'a> FieldParser<'a> {
        }
    }

    fn endianness_suffix(&'a self, width: usize) -> &'static str {
        if width > 8 && self.endianness == ast::EndiannessValue::LittleEndian {
            "_le"
        } else {
            ""
        }
    }

    /// Parse an unsigned integer with the given `width`.
    ///
    /// The generated code requires that `self.span` is a mutable
    /// `bytes::Buf` value.
    fn get_uint(&self, width: usize) -> proc_macro2::TokenStream {
        let span = &self.span;
        let suffix = self.endianness_suffix(width);
        let value_type = types::Integer::new(width);
        if value_type.width == width {
            let get_u = format_ident!("get_u{}{}", value_type.width, suffix);
            quote! {
                #span.#get_u()
            }
        } else {
            let get_uint = format_ident!("get_uint{}", suffix);
            let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8);
            let cast = (value_type.width < 64).then(|| quote!(as #value_type));
            quote! {
                #span.#get_uint(#value_nbytes) #cast
            }
        }
    }

    pub fn add(&mut self, field: &'a ast::Field) {
        if field.is_bitfield(self.scope) {
            self.add_bit_field(field);
@@ -107,7 +76,7 @@ impl<'a> FieldParser<'a> {
        // semantic in Rust.
        let chunk_name = format_ident!("chunk");

        let get = self.get_uint(self.shift);
        let get = types::get_uint(self.endianness, self.shift, self.span);
        if self.chunk.len() > 1 {
            // Multiple values: we read into a local variable.
            self.code.push(quote! {
+3 −38
Original line number Diff line number Diff line
@@ -36,41 +36,6 @@ impl<'a> FieldSerializer<'a> {
        }
    }

    fn endianness_suffix(&'a self, width: usize) -> &'static str {
        if width > 8 && self.endianness == ast::EndiannessValue::LittleEndian {
            "_le"
        } else {
            ""
        }
    }

    /// Write an unsigned integer `value` to `self.span`.
    ///
    /// The generated code requires that `self.span` is a mutable
    /// `bytes::BufMut` value.
    fn put_uint(
        &'a self,
        value: &proc_macro2::TokenStream,
        width: usize,
    ) -> proc_macro2::TokenStream {
        let span = &self.span;
        let suffix = self.endianness_suffix(width);
        let value_type = types::Integer::new(width);
        if value_type.width == width {
            let put_u = format_ident!("put_u{}{}", width, suffix);
            quote! {
                #span.#put_u(#value)
            }
        } else {
            let put_uint = format_ident!("put_uint{}", suffix);
            let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8);
            let cast = (value_type.width < 64).then(|| quote!(as u64));
            quote! {
                #span.#put_uint(#value #cast, #value_nbytes)
            }
        }
    }

    pub fn add(&mut self, field: &ast::Field) {
        if field.is_bitfield(self.scope) {
            self.add_bit_field(field);
@@ -132,7 +97,7 @@ impl<'a> FieldSerializer<'a> {
                if chunk_len > 1 {
                    // We will be combining values with `|`, so we
                    // need to cast them first. If there is a single
                    // value in the chunk, `self.put_uint` will cast.
                    // value in the chunk, `put_uint` will cast.
                    value = quote! { (#value as #chunk_type) };
                }
                if shift > 0 {
@@ -147,13 +112,13 @@ impl<'a> FieldSerializer<'a> {
        match values.as_slice() {
            [] => todo!(),
            [value] => {
                let put = self.put_uint(value, self.shift);
                let put = types::put_uint(self.endianness, value, self.shift, self.span);
                self.code.push(quote! {
                    #put;
                });
            }
            _ => {
                let put = self.put_uint(&quote!(value), self.shift);
                let put = types::put_uint(self.endianness, &quote!(value), self.shift, self.span);
                self.code.push(quote! {
                    let value = #(#values)|*;
                    #put;
+63 −0
Original line number Diff line number Diff line
@@ -47,6 +47,69 @@ pub fn rust_type(field: &ast::Field) -> proc_macro2::TokenStream {
    }
}

/// Suffix for `Buf::get_*` and `BufMut::put_*` methods when reading a
/// value with the given `width`.
fn endianness_suffix(endianness: ast::EndiannessValue, width: usize) -> &'static str {
    if width > 8 && endianness == ast::EndiannessValue::LittleEndian {
        "_le"
    } else {
        ""
    }
}

/// Parse an unsigned integer with the given `width`.
///
/// The generated code requires that `span` is a mutable `bytes::Buf`
/// value.
pub fn get_uint(
    endianness: ast::EndiannessValue,
    width: usize,
    span: &proc_macro2::Ident,
) -> proc_macro2::TokenStream {
    let suffix = endianness_suffix(endianness, width);
    let value_type = Integer::new(width);
    if value_type.width == width {
        let get_u = format_ident!("get_u{}{}", value_type.width, suffix);
        quote! {
            #span.#get_u()
        }
    } else {
        let get_uint = format_ident!("get_uint{}", suffix);
        let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8);
        let cast = (value_type.width < 64).then(|| quote!(as #value_type));
        quote! {
            #span.#get_uint(#value_nbytes) #cast
        }
    }
}

/// Write an unsigned integer `value` to `span`.
///
/// The generated code requires that `span` is a mutable
/// `bytes::BufMut` value.
pub fn put_uint(
    endianness: ast::EndiannessValue,
    value: &proc_macro2::TokenStream,
    width: usize,
    span: &proc_macro2::Ident,
) -> proc_macro2::TokenStream {
    let suffix = endianness_suffix(endianness, width);
    let value_type = Integer::new(width);
    if value_type.width == width {
        let put_u = format_ident!("put_u{}{}", width, suffix);
        quote! {
            #span.#put_u(#value)
        }
    } else {
        let put_uint = format_ident!("put_uint{}", suffix);
        let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8);
        let cast = (value_type.width < 64).then(|| quote!(as u64));
        quote! {
            #span.#put_uint(#value #cast, #value_nbytes)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;