<commit_before>use std::result::Result;

use silkthread_base::*;
use silkthread_base::basic::*;

use super::super::lex::lex_tool::*;
use super::script::*;

///
/// Represents a parse error
///
#[derive(Serialize, Deserialize, Debug)]
pub struct ParseError {

}

///
/// Tool that parses our scripting language
///
pub struct ParseScriptTool {
}

impl ParseError {
    pub fn new() -> ParseError {
        ParseError { }
    }
}

struct ParseState<'a> {
    remaining: &'a [ScriptToken]
}

impl<'a> ParseState<'a> {
    ///
    /// Returns true if a token is considered syntax (gets returned from lookahead)
    ///
    fn is_syntax(token: &ScriptToken) -> bool {
        match token.token {
            ScriptLexerToken::Whitespace    |
            ScriptLexerToken::Comment       => false,

            _                               => true
        }
    }

    ///
    /// Looks ahead to the next syntactically relevant lexer match (and returns the tokens after it)
    ///
    fn lookahead(&self) -> Option<(&'a ScriptToken, &'a [ScriptToken])> {
        let mut index   = 0;
        let len         = self.remaining.len();

        loop {
            if index >= len {
                return None;
            } else if ParseState::is_syntax(&self.remaining[index]) {
                let token       = &self.remaining[index];
                let remaining   = &self.remaining[index+1..len];
                return Some((token, remaining));
            }

            index += 1;
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn lookahead_is(&self, token: ScriptLexerToken) -> bool {
        if let Some((lookahead, _remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches
                true
            } else {
                // Token does not match
                false
            }
        } else {
            // End of file
            if token == ScriptLexerToken::EndOfFile {
                // With lookahead_is we can look for the end of file (but we can't accept it because there's no token data associated with it)
                true
            } else {
                false
            }
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn accept(&mut self, token: ScriptLexerToken) -> Option<&'a ScriptToken> {
        if let Some((lookahead, remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches: remove it from the input and return it
                self.remaining = remaining;
                Some(lookahead)
            } else {
                // Next token does not match
                None
            }
        } else {
            // Reached the end of file
            None
        }
    }

    ///
    /// Parses a statement
    ///
    pub fn parse_statement(&mut self) -> Result<Script, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Newlines are ignored
            self.parse_statement()

        } else if self.accept(ScriptLexerToken::Let).is_some() {
            // let identifier = expression
            self.parse_let()

        } else if self.accept(ScriptLexerToken::Var).is_some() {
            // var identifier = expression
            self.parse_var()

        } else if self.accept(ScriptLexerToken::Def).is_some() {
            // def fn args { statements }
            self.parse_def()

        } else if self.accept(ScriptLexerToken::If).is_some() {
            // if expression { statements }
            self.parse_if()

        } else if self.accept(ScriptLexerToken::Using).is_some() {
            // using expression { statements }
            self.parse_using()

        } else if self.accept(ScriptLexerToken::While).is_some() {
            // while expression { statements }
            self.parse_while()

        } else if self.accept(ScriptLexerToken::Loop).is_some() {
            // loop { statements }
            self.parse_loop()

        } else if self.accept(ScriptLexerToken::For).is_some() {
            // for identifier in expression { statements }
            self.parse_for()

        } else if self.lookahead_is(ScriptLexerToken::Identifier) {
            // While commands are either <Expression> or <Expression> <Expression>, we
            // force the first expression to be an identifier at the moment
            self.parse_command()

        } else {
            // Unrecognised token
            Err(ParseError::new())
        }
    }

    ///
    /// Parses a command
    ///
    /// Syntax '<expression>', '<expression> <expression>'
    ///
    pub fn parse_command(&mut self) -> Result<Script, ParseError> {
        // Starts with an expression specifying the command to run
        self.parse_expression().and_then(move |command_expression| {
            // Followed by arguments (or an end-of-expression marker)
            if self.accept(ScriptLexerToken::Newline).is_some()
               || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                // Newline or EOF ends a command
                Ok(Script::RunCommand(command_expression, None))

            } else {
                // Anything else should be an argument expression
                self.parse_expression().and_then(move |argument_expression| {
                    Ok(Script::RunCommand(command_expression, Some(argument_expression)))

                }).and_then(move |command| {
                    // Command must be followed by a newline
                    if self.accept(ScriptLexerToken::Newline).is_some()
                       || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                        Ok(command)
                    } else {
                        Err(ParseError::new())
                    }

                })

            }
        })
    }

    ///
    /// Parses an Expression
    ///
    pub fn parse_expression(&mut self) -> Result<Expression, ParseError> {
        // Get the LHS of the expression
        let left_expr = self.parse_simple_expression();

        // Look for a RHS
        left_expr.and_then(|left_expr| {
            if self.accept(ScriptLexerToken::Symbol(String::from("."))).is_some() {
                // 'a.b' field access
                let right_expr = self.parse_expression();

                right_expr.map(|right_expr| Expression::FieldAccess(Box::new((left_expr, right_expr))))

            } else if self.accept(ScriptLexerToken::Symbol(String::from("["))).is_some() {
                // a[b] indexing
                let right_expr = self.parse_expression();

                right_expr.and_then(|right_expr| {
                    if self.accept(ScriptLexerToken::Symbol(String::from("]"))).is_some() {
                        // Got all of a[b]
                        Ok(Expression::Index(Box::new((left_expr, right_expr))))
                    } else {
                        // Missing ']'
                        Err(ParseError::new())
                    }
                })

            } else {
                Ok(left_expr)

            }
        })
    }

    ///
    /// Parses a simple expression
    ///
    pub fn parse_simple_expression(&mut self) -> Result<Expression, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Ignore newlines within an expression
            self.parse_expression()

        } else if let Some(identifier) = self.accept(ScriptLexerToken::Identifier) {
            // Simple expression
            Ok(Expression::Identifier(identifier.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::Number) {
            // Simple expression
            Ok(Expression::Number(number.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::HexNumber) {
            // Hex numbers work like normal numbers
            Ok(Expression::Number(number.clone()))

        } else if let Some(string) = self.accept(ScriptLexerToken::String) {
            // Simple expression
            Ok(Expression::String(string.clone()))

        } else {
            // Syntax error
            Err(ParseError::new())

        }
    }

    pub fn parse_let(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_var(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_def(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_if(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_using(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_while(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_loop(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_for(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }
}

impl ParseScriptTool {
    ///
    /// Creates a new tool from the parse script tool
    ///
    pub fn new_tool() -> Box<Tool> {
        Box::new(make_tool(move |script: Vec<LexerMatch>| -> Result<Vec<Script>, ParseError> {
            ParseScriptTool::parse(&script)
        }))
    }

    ///
    /// Tries to parse a script from the output of the lexer
    ///
    pub fn parse(input: &[LexerMatch]) -> Result<Vec<Script>, ParseError> {
        // Convert to script tokens
        let as_script_token: Vec<ScriptToken> = input
            .iter()
            .map(|token| ScriptToken::from_lexer_match(token))
            .collect();

        // Parse until we reach the end of the file
        let mut parser = ParseState { remaining: &as_script_token };
        let mut result = vec![];

        while !parser.lookahead_is(ScriptLexerToken::EndOfFile) {
            let next_statement = parser.parse_statement();

            match next_statement {
                // Fail out if we get a parse failure
                Err(failure)        => return Err(failure),

                // Build out the result otherwise
                Ok(next_statement)  => result.push(next_statement)
            }

            // Swallow any trailing newlines
            while parser.accept(ScriptLexerToken::Newline).is_some() { }
        }

        Ok(result)
    }
}

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

    ///
    /// Performs lexing
    ///
    fn lex(text: &str) -> Vec<LexerMatch> {
        let lexer = create_lex_script_tool();

        lexer.lex(text)
    }

    fn parse(text: &str) -> Result<Vec<Script>, ParseError> {
        let lexed = lex(text);
        ParseScriptTool::parse(&lexed)
    }

    #[test]
    fn can_parse_command_statement() {
        let statement   = "some-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_field_access() {
        let statement   = "some-command.some-field";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::FieldAccess(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_array_indexing() {
        let statement   = "some-command[0]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Index(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_parameter() {
        let statement   = "some-command 1";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Number(_))) => true, _ => false});
    }

    #[test]
    fn cannot_try_to_put_multiple_statements_on_one_line() {
        let statement   = "some-command 1 some-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_err());
    }

    #[test]
    fn can_parse_multiple_lines() {
        let statement   = "some-command\nsome-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());
        assert!(parsed.unwrap().len() == 2);
    }
}
<commit_msg>Factor into different methods<commit_after>use std::result::Result;

use silkthread_base::*;
use silkthread_base::basic::*;

use super::super::lex::lex_tool::*;
use super::script::*;

///
/// Represents a parse error
///
#[derive(Serialize, Deserialize, Debug)]
pub struct ParseError {

}

///
/// Tool that parses our scripting language
///
pub struct ParseScriptTool {
}

impl ParseError {
    pub fn new() -> ParseError {
        ParseError { }
    }
}

struct ParseState<'a> {
    remaining: &'a [ScriptToken]
}

impl<'a> ParseState<'a> {
    ///
    /// Returns true if a token is considered syntax (gets returned from lookahead)
    ///
    fn is_syntax(token: &ScriptToken) -> bool {
        match token.token {
            ScriptLexerToken::Whitespace    |
            ScriptLexerToken::Comment       => false,

            _                               => true
        }
    }

    ///
    /// Looks ahead to the next syntactically relevant lexer match (and returns the tokens after it)
    ///
    fn lookahead(&self) -> Option<(&'a ScriptToken, &'a [ScriptToken])> {
        let mut index   = 0;
        let len         = self.remaining.len();

        loop {
            if index >= len {
                return None;
            } else if ParseState::is_syntax(&self.remaining[index]) {
                let token       = &self.remaining[index];
                let remaining   = &self.remaining[index+1..len];
                return Some((token, remaining));
            }

            index += 1;
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn lookahead_is(&self, token: ScriptLexerToken) -> bool {
        if let Some((lookahead, _remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches
                true
            } else {
                // Token does not match
                false
            }
        } else {
            // End of file
            if token == ScriptLexerToken::EndOfFile {
                // With lookahead_is we can look for the end of file (but we can't accept it because there's no token data associated with it)
                true
            } else {
                false
            }
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn accept(&mut self, token: ScriptLexerToken) -> Option<&'a ScriptToken> {
        if let Some((lookahead, remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches: remove it from the input and return it
                self.remaining = remaining;
                Some(lookahead)
            } else {
                // Next token does not match
                None
            }
        } else {
            // Reached the end of file
            None
        }
    }

    ///
    /// Parses a statement
    ///
    pub fn parse_statement(&mut self) -> Result<Script, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Newlines are ignored
            self.parse_statement()

        } else if self.accept(ScriptLexerToken::Let).is_some() {
            // let identifier = expression
            self.parse_let()

        } else if self.accept(ScriptLexerToken::Var).is_some() {
            // var identifier = expression
            self.parse_var()

        } else if self.accept(ScriptLexerToken::Def).is_some() {
            // def fn args { statements }
            self.parse_def()

        } else if self.accept(ScriptLexerToken::If).is_some() {
            // if expression { statements }
            self.parse_if()

        } else if self.accept(ScriptLexerToken::Using).is_some() {
            // using expression { statements }
            self.parse_using()

        } else if self.accept(ScriptLexerToken::While).is_some() {
            // while expression { statements }
            self.parse_while()

        } else if self.accept(ScriptLexerToken::Loop).is_some() {
            // loop { statements }
            self.parse_loop()

        } else if self.accept(ScriptLexerToken::For).is_some() {
            // for identifier in expression { statements }
            self.parse_for()

        } else if self.lookahead_is(ScriptLexerToken::Identifier) {
            // While commands are either <Expression> or <Expression> <Expression>, we
            // force the first expression to be an identifier at the moment
            self.parse_command()

        } else {
            // Unrecognised token
            Err(ParseError::new())
        }
    }

    ///
    /// Parses a command
    ///
    /// Syntax '<expression>', '<expression> <expression>'
    ///
    pub fn parse_command(&mut self) -> Result<Script, ParseError> {
        // Starts with an expression specifying the command to run
        self.parse_expression().and_then(move |command_expression| {
            // Followed by arguments (or an end-of-expression marker)
            if self.accept(ScriptLexerToken::Newline).is_some()
               || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                // Newline or EOF ends a command
                Ok(Script::RunCommand(command_expression, None))

            } else {
                // Anything else should be an argument expression
                self.parse_expression().and_then(move |argument_expression| {
                    Ok(Script::RunCommand(command_expression, Some(argument_expression)))

                }).and_then(move |command| {
                    // Command must be followed by a newline
                    if self.accept(ScriptLexerToken::Newline).is_some()
                       || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                        Ok(command)
                    } else {
                        Err(ParseError::new())
                    }

                })

            }
        })
    }

    ///
    /// Parses an Expression
    ///
    pub fn parse_expression(&mut self) -> Result<Expression, ParseError> {
        // Get the LHS of the expression
        let left_expr = self.parse_simple_expression();

        // Look for a RHS
        left_expr.and_then(|left_expr| self.parse_expression_rhs(left_expr))
    }

    ///
    /// Parses the RHS of an expression (if there is one)
    ///
    pub fn parse_expression_rhs(&mut self, left_expr: Expression) -> Result<Expression, ParseError> {
        if self.accept(ScriptLexerToken::Symbol(String::from("."))).is_some() {
            // 'a.b' field access
            let right_expr = self.parse_expression();

            right_expr.map(|right_expr| Expression::FieldAccess(Box::new((left_expr, right_expr))))

        } else if self.accept(ScriptLexerToken::Symbol(String::from("["))).is_some() {
            // a[b] indexing
            let right_expr = self.parse_expression();

            right_expr.and_then(|right_expr| {
                if self.accept(ScriptLexerToken::Symbol(String::from("]"))).is_some() {
                    // Got all of a[b]
                    Ok(Expression::Index(Box::new((left_expr, right_expr))))
                } else {
                    // Missing ']'
                    Err(ParseError::new())
                }
            })

        } else {
            Ok(left_expr)

        }
    }

    ///
    /// Parses a simple expression
    ///
    pub fn parse_simple_expression(&mut self) -> Result<Expression, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Ignore newlines within an expression
            self.parse_expression()

        } else if let Some(identifier) = self.accept(ScriptLexerToken::Identifier) {
            // Simple expression
            Ok(Expression::Identifier(identifier.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::Number) {
            // Simple expression
            Ok(Expression::Number(number.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::HexNumber) {
            // Hex numbers work like normal numbers
            Ok(Expression::Number(number.clone()))

        } else if let Some(string) = self.accept(ScriptLexerToken::String) {
            // Simple expression
            Ok(Expression::String(string.clone()))

        } else {
            // Syntax error
            Err(ParseError::new())

        }
    }

    pub fn parse_let(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_var(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_def(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_if(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_using(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_while(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_loop(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    pub fn parse_for(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }
}

impl ParseScriptTool {
    ///
    /// Creates a new tool from the parse script tool
    ///
    pub fn new_tool() -> Box<Tool> {
        Box::new(make_tool(move |script: Vec<LexerMatch>| -> Result<Vec<Script>, ParseError> {
            ParseScriptTool::parse(&script)
        }))
    }

    ///
    /// Tries to parse a script from the output of the lexer
    ///
    pub fn parse(input: &[LexerMatch]) -> Result<Vec<Script>, ParseError> {
        // Convert to script tokens
        let as_script_token: Vec<ScriptToken> = input
            .iter()
            .map(|token| ScriptToken::from_lexer_match(token))
            .collect();

        // Parse until we reach the end of the file
        let mut parser = ParseState { remaining: &as_script_token };
        let mut result = vec![];

        while !parser.lookahead_is(ScriptLexerToken::EndOfFile) {
            let next_statement = parser.parse_statement();

            match next_statement {
                // Fail out if we get a parse failure
                Err(failure)        => return Err(failure),

                // Build out the result otherwise
                Ok(next_statement)  => result.push(next_statement)
            }

            // Swallow any trailing newlines
            while parser.accept(ScriptLexerToken::Newline).is_some() { }
        }

        Ok(result)
    }
}

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

    ///
    /// Performs lexing
    ///
    fn lex(text: &str) -> Vec<LexerMatch> {
        let lexer = create_lex_script_tool();

        lexer.lex(text)
    }

    fn parse(text: &str) -> Result<Vec<Script>, ParseError> {
        let lexed = lex(text);
        ParseScriptTool::parse(&lexed)
    }

    #[test]
    fn can_parse_command_statement() {
        let statement   = "some-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_field_access() {
        let statement   = "some-command.some-field";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::FieldAccess(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_array_indexing() {
        let statement   = "some-command[0]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Index(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_parameter() {
        let statement   = "some-command 1";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Number(_))) => true, _ => false});
    }

    #[test]
    fn cannot_try_to_put_multiple_statements_on_one_line() {
        let statement   = "some-command 1 some-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_err());
    }

    #[test]
    fn can_parse_multiple_lines() {
        let statement   = "some-command\nsome-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());
        assert!(parsed.unwrap().len() == 2);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::{
    error::{Error, Result},
    format::*,
    trace::{Samples, Tracer},
    value::Value,
};
use serde::{ser, Serialize};

/// Serialize a single value.
/// The lifetime 'a is set by the serialization call site and the `&'a mut`
/// references used to return tracing results and serialization samples.
pub(crate) struct Serializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,
}

impl<'a> Serializer<'a> {
    pub(crate) fn new(tracer: &'a mut Tracer, samples: &'a mut Samples) -> Self {
        Self { tracer, samples }
    }
}

impl<'a> ser::Serializer for Serializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;
    type SerializeSeq = SeqSerializer<'a>;
    type SerializeTuple = TupleSerializer<'a>;
    type SerializeTupleStruct = TupleStructSerializer<'a>;
    type SerializeTupleVariant = TupleVariantSerializer<'a>;
    type SerializeMap = MapSerializer<'a>;
    type SerializeStruct = StructSerializer<'a>;
    type SerializeStructVariant = StructVariantSerializer<'a>;

    fn serialize_bool(self, v: bool) -> Result<(Format, Value)> {
        Ok((Format::Bool, Value::Bool(v)))
    }

    fn serialize_i8(self, v: i8) -> Result<(Format, Value)> {
        Ok((Format::I8, Value::I8(v)))
    }

    fn serialize_i16(self, v: i16) -> Result<(Format, Value)> {
        Ok((Format::I16, Value::I16(v)))
    }

    fn serialize_i32(self, v: i32) -> Result<(Format, Value)> {
        Ok((Format::I32, Value::I32(v)))
    }

    fn serialize_i64(self, v: i64) -> Result<(Format, Value)> {
        Ok((Format::I64, Value::I64(v)))
    }

    fn serialize_i128(self, v: i128) -> Result<(Format, Value)> {
        Ok((Format::I128, Value::I128(v)))
    }

    fn serialize_u8(self, v: u8) -> Result<(Format, Value)> {
        Ok((Format::U8, Value::U8(v)))
    }

    fn serialize_u16(self, v: u16) -> Result<(Format, Value)> {
        Ok((Format::U16, Value::U16(v)))
    }

    fn serialize_u32(self, v: u32) -> Result<(Format, Value)> {
        Ok((Format::U32, Value::U32(v)))
    }

    fn serialize_u64(self, v: u64) -> Result<(Format, Value)> {
        Ok((Format::U64, Value::U64(v)))
    }

    fn serialize_u128(self, v: u128) -> Result<(Format, Value)> {
        Ok((Format::U128, Value::U128(v)))
    }

    fn serialize_f32(self, v: f32) -> Result<(Format, Value)> {
        Ok((Format::F32, Value::F32(v)))
    }

    fn serialize_f64(self, v: f64) -> Result<(Format, Value)> {
        Ok((Format::F64, Value::F64(v)))
    }

    fn serialize_char(self, v: char) -> Result<(Format, Value)> {
        Ok((Format::Char, Value::Char(v)))
    }

    fn serialize_str(self, v: &str) -> Result<(Format, Value)> {
        Ok((Format::Str, Value::Str(v.into())))
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<(Format, Value)> {
        Ok((Format::Bytes, Value::Bytes(v.into())))
    }

    fn serialize_none(self) -> Result<(Format, Value)> {
        Ok((Format::unknown(), Value::Option(None)))
    }

    fn serialize_some<T>(self, v: &T) -> Result<(Format, Value)>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = v.serialize(self)?;
        Ok((
            Format::Option(Box::new(format)),
            Value::Option(Some(Box::new(value))),
        ))
    }

    fn serialize_unit(self) -> Result<(Format, Value)> {
        Ok((Format::Unit, Value::Unit))
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(Format, Value)> {
        self.tracer.record_container(
            self.samples,
            name,
            ContainerFormat::UnitStruct,
            Value::Unit,
            false,
        )
    }

    fn serialize_unit_variant(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
    ) -> Result<(Format, Value)> {
        self.tracer.record_variant(
            self.samples,
            name,
            variant_index,
            variant_name,
            VariantFormat::Unit,
            Value::Unit,
        )
    }

    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<(Format, Value)>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.tracer.record_container(
            self.samples,
            name,
            ContainerFormat::NewTypeStruct(Box::new(format)),
            value,
            self.tracer.config.record_samples_for_newtype_structs,
        )
    }

    fn serialize_newtype_variant<T>(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
        value: &T,
    ) -> Result<(Format, Value)>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.tracer.record_variant(
            self.samples,
            name,
            variant_index,
            variant_name,
            VariantFormat::NewType(Box::new(format)),
            value,
        )
    }

    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
        Ok(SeqSerializer {
            tracer: self.tracer,
            samples: self.samples,
            format: Format::unknown(),
            values: Vec::new(),
        })
    }

    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
        Ok(TupleSerializer {
            tracer: self.tracer,
            samples: self.samples,
            formats: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_tuple_struct(
        self,
        name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleStruct> {
        Ok(TupleStructSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            formats: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_tuple_variant(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleVariant> {
        Ok(TupleVariantSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            variant_index,
            variant_name,
            formats: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
        Ok(MapSerializer {
            tracer: self.tracer,
            samples: self.samples,
            key_format: Format::unknown(),
            value_format: Format::unknown(),
            values: Vec::new(),
        })
    }

    fn serialize_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
        Ok(StructSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            fields: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_struct_variant(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStructVariant> {
        Ok(StructVariantSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            variant_index,
            variant_name,
            fields: Vec::new(),
            values: Vec::new(),
        })
    }

    fn is_human_readable(&self) -> bool {
        self.tracer.config.is_human_readable
    }
}

pub struct SeqSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    format: Format,
    values: Vec<Value>,
}

impl<'a> ser::SerializeSeq for SeqSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.format.unify(format)?;
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        Ok((Format::Seq(Box::new(self.format)), Value::Seq(self.values)))
    }
}

pub struct TupleSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    formats: Vec<Format>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeTuple for TupleSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.formats.push(format);
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        Ok((Format::Tuple(self.formats), Value::Seq(self.values)))
    }
}

pub struct TupleStructSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    name: &'static str,
    formats: Vec<Format>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeTupleStruct for TupleStructSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.formats.push(format);
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let format = ContainerFormat::TupleStruct(self.formats);
        let value = Value::Seq(self.values);
        self.tracer.record_container(
            self.samples,
            self.name,
            format,
            value,
            self.tracer.config.record_samples_for_tuple_structs,
        )
    }
}

pub struct TupleVariantSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    name: &'static str,
    variant_index: u32,
    variant_name: &'static str,
    formats: Vec<Format>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeTupleVariant for TupleVariantSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, v: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = v.serialize(Serializer::new(self.tracer, self.samples))?;
        self.formats.push(format);
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let variant = VariantFormat::Tuple(self.formats);
        let value = Value::Seq(self.values);
        self.tracer.record_variant(
            self.samples,
            self.name,
            self.variant_index,
            self.variant_name,
            variant,
            value,
        )
    }
}

pub struct MapSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    key_format: Format,
    value_format: Format,
    values: Vec<Value>,
}

impl<'a> ser::SerializeMap for MapSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = key.serialize(Serializer::new(self.tracer, self.samples))?;
        self.key_format.unify(format)?;
        self.values.push(value);
        Ok(())
    }

    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.value_format.unify(format)?;
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let format = Format::Map {
            key: Box::new(self.key_format),
            value: Box::new(self.value_format),
        };
        let value = Value::Seq(self.values);
        Ok((format, value))
    }
}

pub struct StructSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    name: &'static str,
    fields: Vec<Named<Format>>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeStruct for StructSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, name: &'static str, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.fields.push(Named {
            name: name.into(),
            value: format,
        });
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let format = ContainerFormat::Struct(self.fields);
        let value = Value::Seq(self.values);
        self.tracer.record_container(
            self.samples,
            self.name,
            format,
            value,
            self.tracer.config.record_samples_for_structs,
        )
    }
}

pub struct StructVariantSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,
    name: &'static str,
    variant_index: u32,
    variant_name: &'static str,
    fields: Vec<Named<Format>>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeStructVariant for StructVariantSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, name: &'static str, value: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = value.serialize(Serializer::new(self.tracer, self.samples))?;
        self.fields.push(Named {
            name: name.into(),
            value: format,
        });
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let variant = VariantFormat::Struct(self.fields);
        let value = Value::Seq(self.values);
        self.tracer.record_variant(
            self.samples,
            self.name,
            self.variant_index,
            self.variant_name,
            variant,
            value,
        )
    }
}
<commit_msg>[serde-reflection][nit] rename variable to avoid type confusion<commit_after>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::{
    error::{Error, Result},
    format::*,
    trace::{Samples, Tracer},
    value::Value,
};
use serde::{ser, Serialize};

/// Serialize a single value.
/// The lifetime 'a is set by the serialization call site and the `&'a mut`
/// references used to return tracing results and serialization samples.
pub(crate) struct Serializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,
}

impl<'a> Serializer<'a> {
    pub(crate) fn new(tracer: &'a mut Tracer, samples: &'a mut Samples) -> Self {
        Self { tracer, samples }
    }
}

impl<'a> ser::Serializer for Serializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;
    type SerializeSeq = SeqSerializer<'a>;
    type SerializeTuple = TupleSerializer<'a>;
    type SerializeTupleStruct = TupleStructSerializer<'a>;
    type SerializeTupleVariant = TupleVariantSerializer<'a>;
    type SerializeMap = MapSerializer<'a>;
    type SerializeStruct = StructSerializer<'a>;
    type SerializeStructVariant = StructVariantSerializer<'a>;

    fn serialize_bool(self, content: bool) -> Result<(Format, Value)> {
        Ok((Format::Bool, Value::Bool(content)))
    }

    fn serialize_i8(self, content: i8) -> Result<(Format, Value)> {
        Ok((Format::I8, Value::I8(content)))
    }

    fn serialize_i16(self, content: i16) -> Result<(Format, Value)> {
        Ok((Format::I16, Value::I16(content)))
    }

    fn serialize_i32(self, content: i32) -> Result<(Format, Value)> {
        Ok((Format::I32, Value::I32(content)))
    }

    fn serialize_i64(self, content: i64) -> Result<(Format, Value)> {
        Ok((Format::I64, Value::I64(content)))
    }

    fn serialize_i128(self, content: i128) -> Result<(Format, Value)> {
        Ok((Format::I128, Value::I128(content)))
    }

    fn serialize_u8(self, content: u8) -> Result<(Format, Value)> {
        Ok((Format::U8, Value::U8(content)))
    }

    fn serialize_u16(self, content: u16) -> Result<(Format, Value)> {
        Ok((Format::U16, Value::U16(content)))
    }

    fn serialize_u32(self, content: u32) -> Result<(Format, Value)> {
        Ok((Format::U32, Value::U32(content)))
    }

    fn serialize_u64(self, content: u64) -> Result<(Format, Value)> {
        Ok((Format::U64, Value::U64(content)))
    }

    fn serialize_u128(self, content: u128) -> Result<(Format, Value)> {
        Ok((Format::U128, Value::U128(content)))
    }

    fn serialize_f32(self, content: f32) -> Result<(Format, Value)> {
        Ok((Format::F32, Value::F32(content)))
    }

    fn serialize_f64(self, content: f64) -> Result<(Format, Value)> {
        Ok((Format::F64, Value::F64(content)))
    }

    fn serialize_char(self, content: char) -> Result<(Format, Value)> {
        Ok((Format::Char, Value::Char(content)))
    }

    fn serialize_str(self, content: &str) -> Result<(Format, Value)> {
        Ok((Format::Str, Value::Str(content.into())))
    }

    fn serialize_bytes(self, content: &[u8]) -> Result<(Format, Value)> {
        Ok((Format::Bytes, Value::Bytes(content.into())))
    }

    fn serialize_none(self) -> Result<(Format, Value)> {
        Ok((Format::unknown(), Value::Option(None)))
    }

    fn serialize_some<T>(self, content: &T) -> Result<(Format, Value)>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(self)?;
        Ok((
            Format::Option(Box::new(format)),
            Value::Option(Some(Box::new(value))),
        ))
    }

    fn serialize_unit(self) -> Result<(Format, Value)> {
        Ok((Format::Unit, Value::Unit))
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(Format, Value)> {
        self.tracer.record_container(
            self.samples,
            name,
            ContainerFormat::UnitStruct,
            Value::Unit,
            false,
        )
    }

    fn serialize_unit_variant(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
    ) -> Result<(Format, Value)> {
        self.tracer.record_variant(
            self.samples,
            name,
            variant_index,
            variant_name,
            VariantFormat::Unit,
            Value::Unit,
        )
    }

    fn serialize_newtype_struct<T>(self, name: &'static str, content: &T) -> Result<(Format, Value)>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.tracer.record_container(
            self.samples,
            name,
            ContainerFormat::NewTypeStruct(Box::new(format)),
            value,
            self.tracer.config.record_samples_for_newtype_structs,
        )
    }

    fn serialize_newtype_variant<T>(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
        content: &T,
    ) -> Result<(Format, Value)>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.tracer.record_variant(
            self.samples,
            name,
            variant_index,
            variant_name,
            VariantFormat::NewType(Box::new(format)),
            value,
        )
    }

    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
        Ok(SeqSerializer {
            tracer: self.tracer,
            samples: self.samples,
            format: Format::unknown(),
            values: Vec::new(),
        })
    }

    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
        Ok(TupleSerializer {
            tracer: self.tracer,
            samples: self.samples,
            formats: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_tuple_struct(
        self,
        name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleStruct> {
        Ok(TupleStructSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            formats: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_tuple_variant(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleVariant> {
        Ok(TupleVariantSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            variant_index,
            variant_name,
            formats: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
        Ok(MapSerializer {
            tracer: self.tracer,
            samples: self.samples,
            key_format: Format::unknown(),
            value_format: Format::unknown(),
            values: Vec::new(),
        })
    }

    fn serialize_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
        Ok(StructSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            fields: Vec::new(),
            values: Vec::new(),
        })
    }

    fn serialize_struct_variant(
        self,
        name: &'static str,
        variant_index: u32,
        variant_name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStructVariant> {
        Ok(StructVariantSerializer {
            tracer: self.tracer,
            samples: self.samples,
            name,
            variant_index,
            variant_name,
            fields: Vec::new(),
            values: Vec::new(),
        })
    }

    fn is_human_readable(&self) -> bool {
        self.tracer.config.is_human_readable
    }
}

pub struct SeqSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    format: Format,
    values: Vec<Value>,
}

impl<'a> ser::SerializeSeq for SeqSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_element<T>(&mut self, content: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.format.unify(format)?;
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        Ok((Format::Seq(Box::new(self.format)), Value::Seq(self.values)))
    }
}

pub struct TupleSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    formats: Vec<Format>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeTuple for TupleSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_element<T>(&mut self, content: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.formats.push(format);
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        Ok((Format::Tuple(self.formats), Value::Seq(self.values)))
    }
}

pub struct TupleStructSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    name: &'static str,
    formats: Vec<Format>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeTupleStruct for TupleStructSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, content: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.formats.push(format);
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let format = ContainerFormat::TupleStruct(self.formats);
        let value = Value::Seq(self.values);
        self.tracer.record_container(
            self.samples,
            self.name,
            format,
            value,
            self.tracer.config.record_samples_for_tuple_structs,
        )
    }
}

pub struct TupleVariantSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    name: &'static str,
    variant_index: u32,
    variant_name: &'static str,
    formats: Vec<Format>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeTupleVariant for TupleVariantSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, content: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.formats.push(format);
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let variant = VariantFormat::Tuple(self.formats);
        let value = Value::Seq(self.values);
        self.tracer.record_variant(
            self.samples,
            self.name,
            self.variant_index,
            self.variant_name,
            variant,
            value,
        )
    }
}

pub struct MapSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    key_format: Format,
    value_format: Format,
    values: Vec<Value>,
}

impl<'a> ser::SerializeMap for MapSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = key.serialize(Serializer::new(self.tracer, self.samples))?;
        self.key_format.unify(format)?;
        self.values.push(value);
        Ok(())
    }

    fn serialize_value<T>(&mut self, content: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.value_format.unify(format)?;
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let format = Format::Map {
            key: Box::new(self.key_format),
            value: Box::new(self.value_format),
        };
        let value = Value::Seq(self.values);
        Ok((format, value))
    }
}

pub struct StructSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,

    name: &'static str,
    fields: Vec<Named<Format>>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeStruct for StructSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, name: &'static str, content: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.fields.push(Named {
            name: name.into(),
            value: format,
        });
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let format = ContainerFormat::Struct(self.fields);
        let value = Value::Seq(self.values);
        self.tracer.record_container(
            self.samples,
            self.name,
            format,
            value,
            self.tracer.config.record_samples_for_structs,
        )
    }
}

pub struct StructVariantSerializer<'a> {
    tracer: &'a mut Tracer,
    samples: &'a mut Samples,
    name: &'static str,
    variant_index: u32,
    variant_name: &'static str,
    fields: Vec<Named<Format>>,
    values: Vec<Value>,
}

impl<'a> ser::SerializeStructVariant for StructVariantSerializer<'a> {
    type Ok = (Format, Value);
    type Error = Error;

    fn serialize_field<T>(&mut self, name: &'static str, content: &T) -> Result<()>
    where
        T: ?Sized + Serialize,
    {
        let (format, value) = content.serialize(Serializer::new(self.tracer, self.samples))?;
        self.fields.push(Named {
            name: name.into(),
            value: format,
        });
        self.values.push(value);
        Ok(())
    }

    fn end(self) -> Result<(Format, Value)> {
        let variant = VariantFormat::Struct(self.fields);
        let value = Value::Seq(self.values);
        self.tracer.record_variant(
            self.samples,
            self.name,
            self.variant_index,
            self.variant_name,
            variant,
            value,
        )
    }
}
<|endoftext|>


<commit_before>use byteorder::ByteOrder;
use common::bitpacker::BitPacker;
use common::compute_num_bits;
use common::Endianness;
use common::{BinarySerializable, FixedSize};
use directory::ReadOnlySource;
use postings::TermInfo;
use std::cmp;
use std::io;
use std::io::{Read, Write};
use termdict::TermOrdinal;

const BLOCK_LEN: usize = 256;

#[derive(Debug, Eq, PartialEq, Default)]
struct TermInfoBlockMeta {
    offset: u64,
    ref_term_info: TermInfo,
    doc_freq_nbits: u8,
    postings_offset_nbits: u8,
    positions_offset_nbits: u8,
}

impl BinarySerializable for TermInfoBlockMeta {
    fn serialize<W: Write>(&self, write: &mut W) -> io::Result<()> {
        self.offset.serialize(write)?;
        self.ref_term_info.serialize(write)?;
        write.write_all(&[
            self.doc_freq_nbits,
            self.postings_offset_nbits,
            self.positions_offset_nbits,
        ])?;
        Ok(())
    }

    fn deserialize<R: Read>(reader: &mut R) -> io::Result<Self> {
        let offset = u64::deserialize(reader)?;
        let ref_term_info = TermInfo::deserialize(reader)?;
        let mut buffer = [0u8; 3];
        reader.read_exact(&mut buffer)?;
        Ok(TermInfoBlockMeta {
            offset,
            ref_term_info,
            doc_freq_nbits: buffer[0],
            postings_offset_nbits: buffer[1],
            positions_offset_nbits: buffer[2],
        })
    }
}

impl FixedSize for TermInfoBlockMeta {
    const SIZE_IN_BYTES: usize =
        u64::SIZE_IN_BYTES + TermInfo::SIZE_IN_BYTES + 3 * u8::SIZE_IN_BYTES;
}

impl TermInfoBlockMeta {
    fn num_bits(&self) -> u8 {
        self.doc_freq_nbits + self.postings_offset_nbits + self.positions_offset_nbits + 7
    }

    fn deserialize_term_info(&self, data: &[u8], inner_offset: usize) -> TermInfo {
        let num_bits = self.num_bits() as usize;
        let mut cursor = num_bits * inner_offset;

        let doc_freq = extract_bits(data, cursor, self.doc_freq_nbits) as u32;
        cursor += self.doc_freq_nbits as usize;

        let postings_offset = extract_bits(data, cursor, self.postings_offset_nbits);
        cursor += self.postings_offset_nbits as usize;

        let positions_offset = extract_bits(data, cursor, self.positions_offset_nbits);
        cursor += self.positions_offset_nbits as usize;

        let positions_inner_offset = extract_bits(data, cursor, 7) as u8;

        TermInfo {
            doc_freq,
            postings_offset: postings_offset + self.ref_term_info.postings_offset,
            positions_offset: positions_offset + self.ref_term_info.positions_offset,
            positions_inner_offset,
        }
    }
}

pub struct TermInfoStore {
    num_terms: usize,
    block_meta_source: ReadOnlySource,
    term_info_source: ReadOnlySource,
}

fn extract_bits(data: &[u8], addr_bits: usize, num_bits: u8) -> u64 {
    assert!(num_bits <= 56);
    let addr_byte = addr_bits / 8;
    let bit_shift = (addr_bits % 8) as u64;
    let val_unshifted_unmasked: u64 = unsafe { *(data[addr_byte..].as_ptr() as *const u64) };
    let val_shifted_unmasked = val_unshifted_unmasked >> bit_shift;
    let mask = (1u64 << u64::from(num_bits)) - 1;
    val_shifted_unmasked & mask
}

impl TermInfoStore {
    pub fn open(data: &ReadOnlySource) -> TermInfoStore {
        let buffer = data.as_slice();
        let len = Endianness::read_u64(&buffer[0..8]) as usize;
        let num_terms = Endianness::read_u64(&buffer[8..16]) as usize;
        let block_meta_source = data.slice(16, 16 + len);
        let term_info_source = data.slice_from(16 + len);
        TermInfoStore {
            num_terms,
            block_meta_source,
            term_info_source,
        }
    }

    pub fn get(&self, term_ord: TermOrdinal) -> TermInfo {
        let block_id = (term_ord as usize) / BLOCK_LEN;
        let buffer = self.block_meta_source.as_slice();
        let mut block_data: &[u8] = &buffer[block_id * TermInfoBlockMeta::SIZE_IN_BYTES..];
        let term_info_block_data = TermInfoBlockMeta::deserialize(&mut block_data)
            .expect("Failed to deserialize terminfoblockmeta");
        let inner_offset = (term_ord as usize) % BLOCK_LEN;
        if inner_offset == 0 {
            term_info_block_data.ref_term_info
        } else {
            let term_info_data = self.term_info_source.as_slice();
            term_info_block_data.deserialize_term_info(
                &term_info_data[term_info_block_data.offset as usize..],
                inner_offset - 1,
            )
        }
    }

    pub fn num_terms(&self) -> usize {
        self.num_terms
    }
}

pub struct TermInfoStoreWriter {
    buffer_block_metas: Vec<u8>,
    buffer_term_infos: Vec<u8>,
    term_infos: Vec<TermInfo>,
    num_terms: u64,
}

fn bitpack_serialize<W: Write>(
    write: &mut W,
    bit_packer: &mut BitPacker,
    term_info_block_meta: &TermInfoBlockMeta,
    term_info: &TermInfo,
) -> io::Result<()> {
    bit_packer.write(
        u64::from(term_info.doc_freq),
        term_info_block_meta.doc_freq_nbits,
        write,
    )?;
    bit_packer.write(
        term_info.postings_offset,
        term_info_block_meta.postings_offset_nbits,
        write,
    )?;
    bit_packer.write(
        term_info.positions_offset,
        term_info_block_meta.positions_offset_nbits,
        write,
    )?;
    bit_packer.write(u64::from(term_info.positions_inner_offset), 7, write)?;
    Ok(())
}

impl TermInfoStoreWriter {
    pub fn new() -> TermInfoStoreWriter {
        TermInfoStoreWriter {
            buffer_block_metas: Vec::new(),
            buffer_term_infos: Vec::new(),
            term_infos: Vec::with_capacity(BLOCK_LEN),
            num_terms: 0u64,
        }
    }

    fn flush_block(&mut self) -> io::Result<()> {
        if self.term_infos.is_empty() {
            return Ok(());
        }
        let mut bit_packer = BitPacker::new();
        let ref_term_info = self.term_infos[0].clone();
        for term_info in &mut self.term_infos[1..] {
            term_info.postings_offset -= ref_term_info.postings_offset;
            term_info.positions_offset -= ref_term_info.positions_offset;
        }

        let mut max_doc_freq: u32 = 0u32;
        let mut max_postings_offset: u64 = 0u64;
        let mut max_positions_offset: u64 = 0u64;
        for term_info in &self.term_infos[1..] {
            max_doc_freq = cmp::max(max_doc_freq, term_info.doc_freq);
            max_postings_offset = cmp::max(max_postings_offset, term_info.postings_offset);
            max_positions_offset = cmp::max(max_positions_offset, term_info.positions_offset);
        }

        let max_doc_freq_nbits: u8 = compute_num_bits(u64::from(max_doc_freq));
        let max_postings_offset_nbits = compute_num_bits(max_postings_offset);
        let max_positions_offset_nbits = compute_num_bits(max_positions_offset);

        let term_info_block_meta = TermInfoBlockMeta {
            offset: self.buffer_term_infos.len() as u64,
            ref_term_info,
            doc_freq_nbits: max_doc_freq_nbits,
            postings_offset_nbits: max_postings_offset_nbits,
            positions_offset_nbits: max_positions_offset_nbits,
        };

        term_info_block_meta.serialize(&mut self.buffer_block_metas)?;
        for term_info in self.term_infos[1..].iter().cloned() {
            bitpack_serialize(
                &mut self.buffer_term_infos,
                &mut bit_packer,
                &term_info_block_meta,
                &term_info,
            )?;
        }

        // Block need end up at the end of a byte.
        bit_packer.flush(&mut self.buffer_term_infos)?;
        self.term_infos.clear();

        Ok(())
    }

    pub fn write_term_info(&mut self, term_info: &TermInfo) -> io::Result<()> {
        self.num_terms += 1u64;
        self.term_infos.push(term_info.clone());
        if self.term_infos.len() >= BLOCK_LEN {
            self.flush_block()?;
        }
        Ok(())
    }

    pub fn serialize<W: io::Write>(&mut self, write: &mut W) -> io::Result<()> {
        if !self.term_infos.is_empty() {
            self.flush_block()?;
        }
        let len = self.buffer_block_metas.len() as u64;
        len.serialize(write)?;
        self.num_terms.serialize(write)?;
        write.write_all(&self.buffer_block_metas)?;
        write.write_all(&self.buffer_term_infos)?;
        write.write_all(&[0u8; 7])?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use super::extract_bits;
    use super::TermInfoBlockMeta;
    use super::{TermInfoStore, TermInfoStoreWriter};
    use common;
    use common::bitpacker::BitPacker;
    use common::compute_num_bits;
    use common::BinarySerializable;
    use directory::ReadOnlySource;
    use postings::TermInfo;

    #[test]
    fn test_term_info_block() {
        common::test::fixed_size_test::<TermInfoBlockMeta>();
    }

    #[test]
    fn test_bitpacked() {
        let mut buffer = Vec::new();
        let mut bitpack = BitPacker::new();
        bitpack.write(321u64, 9, &mut buffer).unwrap();
        assert_eq!(compute_num_bits(321u64), 9);
        bitpack.write(2u64, 2, &mut buffer).unwrap();
        assert_eq!(compute_num_bits(2u64), 2);
        bitpack.write(51, 6, &mut buffer).unwrap();
        assert_eq!(compute_num_bits(51), 6);
        bitpack.close(&mut buffer).unwrap();
        assert_eq!(buffer.len(), 3 + 7);
        assert_eq!(extract_bits(&buffer[..], 0, 9), 321u64);
        assert_eq!(extract_bits(&buffer[..], 9, 2), 2u64);
        assert_eq!(extract_bits(&buffer[..], 11, 6), 51u64);
    }

    #[test]
    fn test_term_info_block_meta_serialization() {
        let term_info_block_meta = TermInfoBlockMeta {
            offset: 2009,
            ref_term_info: TermInfo {
                doc_freq: 512,
                postings_offset: 51,
                positions_offset: 3584,
                positions_inner_offset: 0,
            },
            doc_freq_nbits: 10,
            postings_offset_nbits: 5,
            positions_offset_nbits: 11,
        };
        let mut buffer: Vec<u8> = Vec::new();
        term_info_block_meta.serialize(&mut buffer).unwrap();
        let mut cursor: &[u8] = &buffer[..];
        let term_info_block_meta_serde = TermInfoBlockMeta::deserialize(&mut cursor).unwrap();
        assert_eq!(term_info_block_meta_serde, term_info_block_meta);
    }

    #[test]
    fn test_pack() {
        let mut store_writer = TermInfoStoreWriter::new();
        let mut term_infos = vec![];
        for i in 0..1000 {
            let term_info = TermInfo {
                doc_freq: i as u32,
                postings_offset: (i / 10) as u64,
                positions_offset: (i * 7) as u64,
                positions_inner_offset: (i % 128) as u8,
            };
            store_writer.write_term_info(&term_info).unwrap();
            term_infos.push(term_info);
        }
        let mut buffer = Vec::new();
        store_writer.serialize(&mut buffer).unwrap();
        let term_info_store = TermInfoStore::open(&ReadOnlySource::from(buffer));
        for i in 0..1000 {
            assert_eq!(term_info_store.get(i as u64), term_infos[i]);
        }
    }

}
<commit_msg>Removed ptr dereference for explicit ptr::read_unaligned<commit_after>use byteorder::ByteOrder;
use common::bitpacker::BitPacker;
use common::compute_num_bits;
use common::Endianness;
use common::{BinarySerializable, FixedSize};
use directory::ReadOnlySource;
use postings::TermInfo;
use std::cmp;
use std::ptr;
use std::io::{self, Read, Write};
use termdict::TermOrdinal;

const BLOCK_LEN: usize = 256;

#[derive(Debug, Eq, PartialEq, Default)]
struct TermInfoBlockMeta {
    offset: u64,
    ref_term_info: TermInfo,
    doc_freq_nbits: u8,
    postings_offset_nbits: u8,
    positions_offset_nbits: u8,
}

impl BinarySerializable for TermInfoBlockMeta {
    fn serialize<W: Write>(&self, write: &mut W) -> io::Result<()> {
        self.offset.serialize(write)?;
        self.ref_term_info.serialize(write)?;
        write.write_all(&[
            self.doc_freq_nbits,
            self.postings_offset_nbits,
            self.positions_offset_nbits,
        ])?;
        Ok(())
    }

    fn deserialize<R: Read>(reader: &mut R) -> io::Result<Self> {
        let offset = u64::deserialize(reader)?;
        let ref_term_info = TermInfo::deserialize(reader)?;
        let mut buffer = [0u8; 3];
        reader.read_exact(&mut buffer)?;
        Ok(TermInfoBlockMeta {
            offset,
            ref_term_info,
            doc_freq_nbits: buffer[0],
            postings_offset_nbits: buffer[1],
            positions_offset_nbits: buffer[2],
        })
    }
}

impl FixedSize for TermInfoBlockMeta {
    const SIZE_IN_BYTES: usize =
        u64::SIZE_IN_BYTES + TermInfo::SIZE_IN_BYTES + 3 * u8::SIZE_IN_BYTES;
}

impl TermInfoBlockMeta {
    fn num_bits(&self) -> u8 {
        self.doc_freq_nbits + self.postings_offset_nbits + self.positions_offset_nbits + 7
    }

    fn deserialize_term_info(&self, data: &[u8], inner_offset: usize) -> TermInfo {
        let num_bits = self.num_bits() as usize;
        let mut cursor = num_bits * inner_offset;

        let doc_freq = extract_bits(data, cursor, self.doc_freq_nbits) as u32;
        cursor += self.doc_freq_nbits as usize;

        let postings_offset = extract_bits(data, cursor, self.postings_offset_nbits);
        cursor += self.postings_offset_nbits as usize;

        let positions_offset = extract_bits(data, cursor, self.positions_offset_nbits);
        cursor += self.positions_offset_nbits as usize;

        let positions_inner_offset = extract_bits(data, cursor, 7) as u8;

        TermInfo {
            doc_freq,
            postings_offset: postings_offset + self.ref_term_info.postings_offset,
            positions_offset: positions_offset + self.ref_term_info.positions_offset,
            positions_inner_offset,
        }
    }
}

pub struct TermInfoStore {
    num_terms: usize,
    block_meta_source: ReadOnlySource,
    term_info_source: ReadOnlySource,
}

fn extract_bits(data: &[u8], addr_bits: usize, num_bits: u8) -> u64 {
    assert!(num_bits <= 56);
    let addr_byte = addr_bits / 8;
    let bit_shift = (addr_bits % 8) as u64;
    let val_unshifted_unmasked: u64 = unsafe {
        let addr = data.as_ptr().offset(addr_byte as isize) as *const u64;
        ptr::read_unaligned(addr)
    };
    let val_shifted_unmasked = val_unshifted_unmasked >> bit_shift;
    let mask = (1u64 << u64::from(num_bits)) - 1;
    val_shifted_unmasked & mask
}

impl TermInfoStore {
    pub fn open(data: &ReadOnlySource) -> TermInfoStore {
        let buffer = data.as_slice();
        let len = Endianness::read_u64(&buffer[0..8]) as usize;
        let num_terms = Endianness::read_u64(&buffer[8..16]) as usize;
        let block_meta_source = data.slice(16, 16 + len);
        let term_info_source = data.slice_from(16 + len);
        TermInfoStore {
            num_terms,
            block_meta_source,
            term_info_source,
        }
    }

    pub fn get(&self, term_ord: TermOrdinal) -> TermInfo {
        let block_id = (term_ord as usize) / BLOCK_LEN;
        let buffer = self.block_meta_source.as_slice();
        let mut block_data: &[u8] = &buffer[block_id * TermInfoBlockMeta::SIZE_IN_BYTES..];
        let term_info_block_data = TermInfoBlockMeta::deserialize(&mut block_data)
            .expect("Failed to deserialize terminfoblockmeta");
        let inner_offset = (term_ord as usize) % BLOCK_LEN;
        if inner_offset == 0 {
            term_info_block_data.ref_term_info
        } else {
            let term_info_data = self.term_info_source.as_slice();
            term_info_block_data.deserialize_term_info(
                &term_info_data[term_info_block_data.offset as usize..],
                inner_offset - 1,
            )
        }
    }

    pub fn num_terms(&self) -> usize {
        self.num_terms
    }
}

pub struct TermInfoStoreWriter {
    buffer_block_metas: Vec<u8>,
    buffer_term_infos: Vec<u8>,
    term_infos: Vec<TermInfo>,
    num_terms: u64,
}

fn bitpack_serialize<W: Write>(
    write: &mut W,
    bit_packer: &mut BitPacker,
    term_info_block_meta: &TermInfoBlockMeta,
    term_info: &TermInfo,
) -> io::Result<()> {
    bit_packer.write(
        u64::from(term_info.doc_freq),
        term_info_block_meta.doc_freq_nbits,
        write,
    )?;
    bit_packer.write(
        term_info.postings_offset,
        term_info_block_meta.postings_offset_nbits,
        write,
    )?;
    bit_packer.write(
        term_info.positions_offset,
        term_info_block_meta.positions_offset_nbits,
        write,
    )?;
    bit_packer.write(u64::from(term_info.positions_inner_offset), 7, write)?;
    Ok(())
}

impl TermInfoStoreWriter {
    pub fn new() -> TermInfoStoreWriter {
        TermInfoStoreWriter {
            buffer_block_metas: Vec::new(),
            buffer_term_infos: Vec::new(),
            term_infos: Vec::with_capacity(BLOCK_LEN),
            num_terms: 0u64,
        }
    }

    fn flush_block(&mut self) -> io::Result<()> {
        if self.term_infos.is_empty() {
            return Ok(());
        }
        let mut bit_packer = BitPacker::new();
        let ref_term_info = self.term_infos[0].clone();
        for term_info in &mut self.term_infos[1..] {
            term_info.postings_offset -= ref_term_info.postings_offset;
            term_info.positions_offset -= ref_term_info.positions_offset;
        }

        let mut max_doc_freq: u32 = 0u32;
        let mut max_postings_offset: u64 = 0u64;
        let mut max_positions_offset: u64 = 0u64;
        for term_info in &self.term_infos[1..] {
            max_doc_freq = cmp::max(max_doc_freq, term_info.doc_freq);
            max_postings_offset = cmp::max(max_postings_offset, term_info.postings_offset);
            max_positions_offset = cmp::max(max_positions_offset, term_info.positions_offset);
        }

        let max_doc_freq_nbits: u8 = compute_num_bits(u64::from(max_doc_freq));
        let max_postings_offset_nbits = compute_num_bits(max_postings_offset);
        let max_positions_offset_nbits = compute_num_bits(max_positions_offset);

        let term_info_block_meta = TermInfoBlockMeta {
            offset: self.buffer_term_infos.len() as u64,
            ref_term_info,
            doc_freq_nbits: max_doc_freq_nbits,
            postings_offset_nbits: max_postings_offset_nbits,
            positions_offset_nbits: max_positions_offset_nbits,
        };

        term_info_block_meta.serialize(&mut self.buffer_block_metas)?;
        for term_info in self.term_infos[1..].iter().cloned() {
            bitpack_serialize(
                &mut self.buffer_term_infos,
                &mut bit_packer,
                &term_info_block_meta,
                &term_info,
            )?;
        }

        // Block need end up at the end of a byte.
        bit_packer.flush(&mut self.buffer_term_infos)?;
        self.term_infos.clear();

        Ok(())
    }

    pub fn write_term_info(&mut self, term_info: &TermInfo) -> io::Result<()> {
        self.num_terms += 1u64;
        self.term_infos.push(term_info.clone());
        if self.term_infos.len() >= BLOCK_LEN {
            self.flush_block()?;
        }
        Ok(())
    }

    pub fn serialize<W: io::Write>(&mut self, write: &mut W) -> io::Result<()> {
        if !self.term_infos.is_empty() {
            self.flush_block()?;
        }
        let len = self.buffer_block_metas.len() as u64;
        len.serialize(write)?;
        self.num_terms.serialize(write)?;
        write.write_all(&self.buffer_block_metas)?;
        write.write_all(&self.buffer_term_infos)?;
        write.write_all(&[0u8; 7])?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use super::extract_bits;
    use super::TermInfoBlockMeta;
    use super::{TermInfoStore, TermInfoStoreWriter};
    use common;
    use common::bitpacker::BitPacker;
    use common::compute_num_bits;
    use common::BinarySerializable;
    use directory::ReadOnlySource;
    use postings::TermInfo;

    #[test]
    fn test_term_info_block() {
        common::test::fixed_size_test::<TermInfoBlockMeta>();
    }

    #[test]
    fn test_bitpacked() {
        let mut buffer = Vec::new();
        let mut bitpack = BitPacker::new();
        bitpack.write(321u64, 9, &mut buffer).unwrap();
        assert_eq!(compute_num_bits(321u64), 9);
        bitpack.write(2u64, 2, &mut buffer).unwrap();
        assert_eq!(compute_num_bits(2u64), 2);
        bitpack.write(51, 6, &mut buffer).unwrap();
        assert_eq!(compute_num_bits(51), 6);
        bitpack.close(&mut buffer).unwrap();
        assert_eq!(buffer.len(), 3 + 7);
        assert_eq!(extract_bits(&buffer[..], 0, 9), 321u64);
        assert_eq!(extract_bits(&buffer[..], 9, 2), 2u64);
        assert_eq!(extract_bits(&buffer[..], 11, 6), 51u64);
    }

    #[test]
    fn test_term_info_block_meta_serialization() {
        let term_info_block_meta = TermInfoBlockMeta {
            offset: 2009,
            ref_term_info: TermInfo {
                doc_freq: 512,
                postings_offset: 51,
                positions_offset: 3584,
                positions_inner_offset: 0,
            },
            doc_freq_nbits: 10,
            postings_offset_nbits: 5,
            positions_offset_nbits: 11,
        };
        let mut buffer: Vec<u8> = Vec::new();
        term_info_block_meta.serialize(&mut buffer).unwrap();
        let mut cursor: &[u8] = &buffer[..];
        let term_info_block_meta_serde = TermInfoBlockMeta::deserialize(&mut cursor).unwrap();
        assert_eq!(term_info_block_meta_serde, term_info_block_meta);
    }

    #[test]
    fn test_pack() {
        let mut store_writer = TermInfoStoreWriter::new();
        let mut term_infos = vec![];
        for i in 0..1000 {
            let term_info = TermInfo {
                doc_freq: i as u32,
                postings_offset: (i / 10) as u64,
                positions_offset: (i * 7) as u64,
                positions_inner_offset: (i % 128) as u8,
            };
            store_writer.write_term_info(&term_info).unwrap();
            term_infos.push(term_info);
        }
        let mut buffer = Vec::new();
        store_writer.serialize(&mut buffer).unwrap();
        let term_info_store = TermInfoStore::open(&ReadOnlySource::from(buffer));
        for i in 0..1000 {
            assert_eq!(term_info_store.get(i as u64), term_infos[i]);
        }
    }

}
<|endoftext|>


<commit_before>// run-pass

#![allow(deprecated)]
// aux-build:typeid-intrinsic-aux1.rs
// aux-build:typeid-intrinsic-aux2.rs

#![feature(core_intrinsics)]

extern crate typeid_intrinsic_aux1 as other1;
extern crate typeid_intrinsic_aux2 as other2;

use std::hash::{SipHasher, Hasher, Hash};
use std::any::TypeId;

struct A;
struct Test;

pub fn main() {
    assert_eq!(TypeId::of::<other1::A>(), other1::id_A());
    assert_eq!(TypeId::of::<other1::B>(), other1::id_B());
    assert_eq!(TypeId::of::<other1::C>(), other1::id_C());
    assert_eq!(TypeId::of::<other1::D>(), other1::id_D());
    assert_eq!(TypeId::of::<other1::E>(), other1::id_E());
    assert_eq!(TypeId::of::<other1::F>(), other1::id_F());
    assert_eq!(TypeId::of::<other1::G>(), other1::id_G());
    assert_eq!(TypeId::of::<other1::H>(), other1::id_H());
    assert_eq!(TypeId::of::<other1::I>(), other1::id_I());

    assert_eq!(TypeId::of::<other2::A>(), other2::id_A());
    assert_eq!(TypeId::of::<other2::B>(), other2::id_B());
    assert_eq!(TypeId::of::<other2::C>(), other2::id_C());
    assert_eq!(TypeId::of::<other2::D>(), other2::id_D());
    assert_eq!(TypeId::of::<other2::E>(), other2::id_E());
    assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
    assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
    assert_eq!(TypeId::of::<other2::H>(), other2::id_H());
    assert_eq!(TypeId::of::<other1::I>(), other2::id_I());

    assert_eq!(other1::id_F(), other2::id_F());
    assert_eq!(other1::id_G(), other2::id_G());
    assert_eq!(other1::id_H(), other2::id_H());
    assert_eq!(other1::id_I(), other2::id_I());

    assert_eq!(TypeId::of::<isize>(), other2::foo::<isize>());
    assert_eq!(TypeId::of::<isize>(), other1::foo::<isize>());
    assert_eq!(other2::foo::<isize>(), other1::foo::<isize>());
    assert_eq!(TypeId::of::<A>(), other2::foo::<A>());
    assert_eq!(TypeId::of::<A>(), other1::foo::<A>());
    assert_eq!(other2::foo::<A>(), other1::foo::<A>());

    // sanity test of TypeId
    let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
                     TypeId::of::<Test>());
    let (d, e, f) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
                     TypeId::of::<Test>());

    assert!(a != b);
    assert!(a != c);
    assert!(b != c);

    assert_eq!(a, d);
    assert_eq!(b, e);
    assert_eq!(c, f);

    // check it has a hash
    let (a, b) = (TypeId::of::<usize>(), TypeId::of::<usize>());

    let mut s1 = SipHasher::new();
    a.hash(&mut s1);
    let mut s2 = SipHasher::new();
    b.hash(&mut s2);

    assert_eq!(s1.finish(), s2.finish());

    // Check projections

    assert_eq!(TypeId::of::<other1::I32Iterator>(), other1::id_i32_iterator());
    assert_eq!(TypeId::of::<other1::U32Iterator>(), other1::id_u32_iterator());
    assert_eq!(other1::id_i32_iterator(), other2::id_i32_iterator());
    assert_eq!(other1::id_u32_iterator(), other2::id_u32_iterator());
    assert!(other1::id_i32_iterator() != other1::id_u32_iterator());
    assert!(TypeId::of::<other1::I32Iterator>() != TypeId::of::<other1::U32Iterator>());

    // Check fn pointer against collisions
    assert!(TypeId::of::<fn(fn(A) -> A) -> A>() !=
            TypeId::of::<fn(fn() -> A, A) -> A>());
}
<commit_msg>Rollup merge of #63419 - RalfJung:typeid, r=alexcrichton<commit_after>// run-pass

#![allow(deprecated)]
// aux-build:typeid-intrinsic-aux1.rs
// aux-build:typeid-intrinsic-aux2.rs

#![feature(core_intrinsics)]

extern crate typeid_intrinsic_aux1 as other1;
extern crate typeid_intrinsic_aux2 as other2;

use std::hash::{SipHasher, Hasher, Hash};
use std::any::TypeId;

struct A;
struct Test;

pub fn main() {
    assert_eq!(TypeId::of::<other1::A>(), other1::id_A());
    assert_eq!(TypeId::of::<other1::B>(), other1::id_B());
    assert_eq!(TypeId::of::<other1::C>(), other1::id_C());
    assert_eq!(TypeId::of::<other1::D>(), other1::id_D());
    assert_eq!(TypeId::of::<other1::E>(), other1::id_E());
    assert_eq!(TypeId::of::<other1::F>(), other1::id_F());
    assert_eq!(TypeId::of::<other1::G>(), other1::id_G());
    assert_eq!(TypeId::of::<other1::H>(), other1::id_H());
    assert_eq!(TypeId::of::<other1::I>(), other1::id_I());

    assert_eq!(TypeId::of::<other2::A>(), other2::id_A());
    assert_eq!(TypeId::of::<other2::B>(), other2::id_B());
    assert_eq!(TypeId::of::<other2::C>(), other2::id_C());
    assert_eq!(TypeId::of::<other2::D>(), other2::id_D());
    assert_eq!(TypeId::of::<other2::E>(), other2::id_E());
    assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
    assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
    assert_eq!(TypeId::of::<other2::H>(), other2::id_H());
    assert_eq!(TypeId::of::<other1::I>(), other2::id_I());

    assert_eq!(other1::id_F(), other2::id_F());
    assert_eq!(other1::id_G(), other2::id_G());
    assert_eq!(other1::id_H(), other2::id_H());
    assert_eq!(other1::id_I(), other2::id_I());

    assert_eq!(TypeId::of::<isize>(), other2::foo::<isize>());
    assert_eq!(TypeId::of::<isize>(), other1::foo::<isize>());
    assert_eq!(other2::foo::<isize>(), other1::foo::<isize>());
    assert_eq!(TypeId::of::<A>(), other2::foo::<A>());
    assert_eq!(TypeId::of::<A>(), other1::foo::<A>());
    assert_eq!(other2::foo::<A>(), other1::foo::<A>());

    // sanity test of TypeId
    let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
                     TypeId::of::<Test>());
    let (d, e, f) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
                     TypeId::of::<Test>());

    assert!(a != b);
    assert!(a != c);
    assert!(b != c);

    assert_eq!(a, d);
    assert_eq!(b, e);
    assert_eq!(c, f);

    // check it has a hash
    let (a, b) = (TypeId::of::<usize>(), TypeId::of::<usize>());

    let mut s1 = SipHasher::new();
    a.hash(&mut s1);
    let mut s2 = SipHasher::new();
    b.hash(&mut s2);

    assert_eq!(s1.finish(), s2.finish());

    // Check projections

    assert_eq!(TypeId::of::<other1::I32Iterator>(), other1::id_i32_iterator());
    assert_eq!(TypeId::of::<other1::U32Iterator>(), other1::id_u32_iterator());
    assert_eq!(other1::id_i32_iterator(), other2::id_i32_iterator());
    assert_eq!(other1::id_u32_iterator(), other2::id_u32_iterator());
    assert_ne!(other1::id_i32_iterator(), other1::id_u32_iterator());
    assert_ne!(TypeId::of::<other1::I32Iterator>(), TypeId::of::<other1::U32Iterator>());

    // Check fn pointer against collisions
    assert_ne!(
        TypeId::of::<fn(fn(A) -> A) -> A>(),
        TypeId::of::<fn(fn() -> A, A) -> A>()
    );
    assert_ne!(
        TypeId::of::<for<'a> fn(&'a i32) -> &'a i32>(),
        TypeId::of::<for<'a> fn(&'a i32) -> &'static i32>()
    );
    assert_ne!(
        TypeId::of::<for<'a, 'b> fn(&'a i32, &'b i32) -> &'a i32>(),
        TypeId::of::<for<'a, 'b> fn(&'b i32, &'a i32) -> &'a i32>()
    );
}
<|endoftext|>


<commit_before>use stb_image::*;
use stb_image::bindgen::*;
use libc::types::os::arch::c95::c_int;
use ptr::{is_null, to_unsafe_ptr};
use str::as_c_str;
use vec::as_imm_buf;
use vec::raw::from_buf_raw;

pub struct Image<T> {
    width   : uint,
    height  : uint,
    depth   : uint,
    data    : ~[T],
}

pub fn new_image<T>(width: uint, height: uint, depth: uint, data: ~[T]) -> Image<T> {
    Image::<T> {
        width   : width,
        height  : height,
        depth   : depth,
        data    : move data,
    }
}

enum LoadResult {
    Error,
    ImageU8(Image<u8>),
    ImageF32(Image<f32>),
}

pub fn load(path: ~str) -> LoadResult {
    let force_depth = 0;
    load_with_depth(move path, force_depth, false)
}

priv fn load_internal<T>(buf : *T, w : c_int, h : c_int, d : c_int) -> Image<T> {
    unsafe {
        // FIXME: Shouldn't copy; instead we should use a sendable resource. They
        // aren't particularly safe yet though.
        let data = from_buf_raw(buf, (w * h * d) as uint);
        libc::free(buf as *c_void);
        Image::<T>{
            width   : w as uint,
            height  : h as uint,
            depth   : d as uint,
            data    : data}
    }
}

pub fn load_with_depth(path: ~str, force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        do task::unkillable {
            let mut width   = 0 as c_int;
            let mut height  = 0 as c_int;
            let mut depth   = 0 as c_int;
            as_c_str(path, |bytes| {
                if !convert_hdr && stbi_is_hdr(bytes)!=0   {
                    let buffer = stbi_loadf(
                        bytes, to_unsafe_ptr(&width), to_unsafe_ptr(&height),
                        to_unsafe_ptr(&depth), force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageF32( load_internal(buffer,width,height,depth) )
                    }
                } else {
                    let buffer = stbi_load(
                        bytes, to_unsafe_ptr(&width), to_unsafe_ptr(&height),
                        to_unsafe_ptr(&depth), force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageU8( load_internal(buffer,width,height,depth) )
                    }
                }
            })
        }
    }
}

pub fn load_from_memory(buffer: &[u8]) -> LoadResult {
    let force_depth = 0;
    load_from_memory_with_depth(buffer, force_depth, false)
}

pub fn load_from_memory_with_depth(buffer: &[u8], force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        do task::unkillable {
            let mut width = 0 as c_int;
            let mut height = 0 as c_int;
            let mut depth = 0 as c_int;
            as_imm_buf(buffer, |bytes, len| {
                if !convert_hdr && stbi_is_hdr_from_memory(bytes,len as c_int)!=0   {
                    let buffer = stbi_loadf_from_memory(
                        bytes, len as c_int, to_unsafe_ptr(&width),
                        to_unsafe_ptr(&height), to_unsafe_ptr(&depth),
                        force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageF32( load_internal(buffer,width,height,depth) )
                    }
                } else {
                    let buffer = stbi_load_from_memory(
                        bytes, len as c_int, to_unsafe_ptr(&width),
                        to_unsafe_ptr(&height), to_unsafe_ptr(&depth),
                        force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageU8( load_internal(buffer,width,height,depth) )
                    }
                }
            })
        }
    }
}
<commit_msg>Update for language changes<commit_after>use stb_image::*;
use stb_image::bindgen::*;
use libc::types::os::arch::c95::c_int;
use ptr::{is_null, to_unsafe_ptr};
use str::as_c_str;
use vec::as_imm_buf;
use vec::raw::from_buf_raw;

pub struct Image<T> {
    width   : uint,
    height  : uint,
    depth   : uint,
    data    : ~[T],
}

pub fn new_image<T>(width: uint, height: uint, depth: uint, data: ~[T]) -> Image<T> {
    Image::<T> {
        width   : width,
        height  : height,
        depth   : depth,
        data    : move data,
    }
}

pub fn load(path: ~str) -> Option<Image<u8>> {
    unsafe {
        let force_depth = 4;
        load_with_depth(move path, force_depth)
    }
}

pub fn load_with_depth(path: ~str, force_depth: uint) -> Option<Image<u8>> {
    unsafe {
        do task::unkillable {
            let mut width = 0 as c_int;
            let mut height = 0 as c_int;
            let mut depth = 0 as c_int;
            let buffer = as_c_str(path, |bytes| {
                stbi_load(bytes, to_unsafe_ptr(&width), to_unsafe_ptr(&height),
                          to_unsafe_ptr(&depth), force_depth as c_int)
            });

            if is_null(buffer) {
                None
            } else {
                // FIXME: Shouldn't copy; instead we should use a sendable resource. They
                // aren't particularly safe yet though.
                let data = from_buf_raw(buffer, ((width * height) as uint) * force_depth);
                libc::free(buffer as *c_void);
                Some(new_image(width as uint, height as uint, force_depth, move data))
            }
        }
    }
}

pub fn load_from_memory(buffer: &[u8]) -> Option<Image<u8>> {
    unsafe {
        let force_depth = 4;
        load_from_memory_with_depth(buffer, force_depth)
    }
}

pub fn load_from_memory_with_depth(buffer: &[u8], force_depth: uint) -> Option<Image<u8>> {
    unsafe {
        do task::unkillable {
            let mut width = 0 as c_int;
            let mut height = 0 as c_int;
            let mut depth = 0 as c_int;
            let buffer = as_imm_buf(buffer, |bytes, len| {
                stbi_load_from_memory(bytes, len as c_int, to_unsafe_ptr(&width),
                                      to_unsafe_ptr(&height), to_unsafe_ptr(&depth),
                                      force_depth as c_int)
            });

            if is_null(buffer) {
                None
            } else {
                // FIXME: Shouldn't copy; instead we should use a sendable resource. They
                // aren't particularly safe yet though.
                let data = from_buf_raw(buffer, ((width * height) as uint) * force_depth);
                libc::free(buffer as *c_void);
                Some(new_image(width as uint, height as uint, force_depth, move data))
            }
        }
    }
}

<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Jimmy Lu <jimmy.lu.2011@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) fullname

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::path::{is_separator, PathBuf};
use uucore::InvalidEncodingHandling;

static SUMMARY: &str = "Print NAME with any leading directory components removed
If specified, also remove a trailing SUFFIX";

fn usage() -> String {
    format!(
        "{0} NAME [SUFFIX]
    {0} OPTION... NAME...",
        uucore::execution_phrase()
    )
}

pub mod options {
    pub static MULTIPLE: &str = "multiple";
    pub static NAME: &str = "name";
    pub static SUFFIX: &str = "suffix";
    pub static ZERO: &str = "zero";
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();
    let usage = usage();
    //
    // Argument parsing
    //
    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    // too few arguments
    if !matches.is_present(options::NAME) {
        crash!(
            1,
            "{1}\nTry '{0} --help' for more information.",
            uucore::execution_phrase(),
            "missing operand"
        );
    }

    let opt_suffix = matches.is_present(options::SUFFIX);
    let opt_multiple = matches.is_present(options::MULTIPLE);
    let opt_zero = matches.is_present(options::ZERO);
    let multiple_paths = opt_suffix || opt_multiple;
    // too many arguments
    if !multiple_paths && matches.occurrences_of(options::NAME) > 2 {
        crash!(
            1,
            "extra operand '{1}'\nTry '{0} --help' for more information.",
            uucore::execution_phrase(),
            matches.values_of(options::NAME).unwrap().nth(2).unwrap()
        );
    }

    let suffix = if opt_suffix {
        matches.value_of(options::SUFFIX).unwrap()
    } else if !opt_multiple && matches.occurrences_of(options::NAME) > 1 {
        matches.values_of(options::NAME).unwrap().nth(1).unwrap()
    } else {
        ""
    };

    //
    // Main Program Processing
    //

    let paths: Vec<_> = if multiple_paths {
        matches.values_of(options::NAME).unwrap().collect()
    } else {
        matches.values_of(options::NAME).unwrap().take(1).collect()
    };

    let line_ending = if opt_zero { "\0" } else { "\n" };
    for path in paths {
        print!("{}{}", basename(path, suffix), line_ending);
    }

    0
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(SUMMARY)
        .arg(
            Arg::with_name(options::MULTIPLE)
                .short("a")
                .long(options::MULTIPLE)
                .help("support multiple arguments and treat each as a NAME"),
        )
        .arg(Arg::with_name(options::NAME).multiple(true).hidden(true))
        .arg(
            Arg::with_name(options::SUFFIX)
                .short("s")
                .long(options::SUFFIX)
                .value_name("SUFFIX")
                .help("remove a trailing SUFFIX; implies -a"),
        )
        .arg(
            Arg::with_name(options::ZERO)
                .short("z")
                .long(options::ZERO)
                .help("end each output line with NUL, not newline"),
        )
}

fn basename(fullname: &str, suffix: &str) -> String {
    // Remove all platform-specific path separators from the end.
    let path = fullname.trim_end_matches(is_separator);

    // If the path contained *only* suffix characters (for example, if
    // `fullname` were "///" and `suffix` were "/"), then `path` would
    // be left with the empty string. In that case, we set `path` to be
    // the original `fullname` to avoid returning the empty path.
    let path = if path.is_empty() { fullname } else { path };

    // Convert to path buffer and get last path component
    let pb = PathBuf::from(path);
    match pb.components().last() {
        Some(c) => {
            let name = c.as_os_str().to_str().unwrap();
            if name == suffix {
                name.to_string()
            } else {
                name.strip_suffix(suffix).unwrap_or(name).to_string()
            }
        }

        None => "".to_owned(),
    }
}
<commit_msg>basename: use UResult<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Jimmy Lu <jimmy.lu.2011@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) fullname

use clap::{crate_version, App, Arg};
use std::path::{is_separator, PathBuf};
use uucore::display::Quotable;
use uucore::error::{UResult, UUsageError};
use uucore::InvalidEncodingHandling;

static SUMMARY: &str = "Print NAME with any leading directory components removed
If specified, also remove a trailing SUFFIX";

fn usage() -> String {
    format!(
        "{0} NAME [SUFFIX]
    {0} OPTION... NAME...",
        uucore::execution_phrase()
    )
}

pub mod options {
    pub static MULTIPLE: &str = "multiple";
    pub static NAME: &str = "name";
    pub static SUFFIX: &str = "suffix";
    pub static ZERO: &str = "zero";
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();
    let usage = usage();
    //
    // Argument parsing
    //
    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    // too few arguments
    if !matches.is_present(options::NAME) {
        return Err(UUsageError::new(1, "missing operand".to_string()));
    }

    let opt_suffix = matches.is_present(options::SUFFIX);
    let opt_multiple = matches.is_present(options::MULTIPLE);
    let opt_zero = matches.is_present(options::ZERO);
    let multiple_paths = opt_suffix || opt_multiple;
    // too many arguments
    if !multiple_paths && matches.occurrences_of(options::NAME) > 2 {
        return Err(UUsageError::new(
            1,
            format!(
                "extra operand {}",
                matches
                    .values_of(options::NAME)
                    .unwrap()
                    .nth(2)
                    .unwrap()
                    .quote()
            ),
        ));
    }

    let suffix = if opt_suffix {
        matches.value_of(options::SUFFIX).unwrap()
    } else if !opt_multiple && matches.occurrences_of(options::NAME) > 1 {
        matches.values_of(options::NAME).unwrap().nth(1).unwrap()
    } else {
        ""
    };

    //
    // Main Program Processing
    //

    let paths: Vec<_> = if multiple_paths {
        matches.values_of(options::NAME).unwrap().collect()
    } else {
        matches.values_of(options::NAME).unwrap().take(1).collect()
    };

    let line_ending = if opt_zero { "\0" } else { "\n" };
    for path in paths {
        print!("{}{}", basename(path, suffix), line_ending);
    }

    Ok(())
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(SUMMARY)
        .arg(
            Arg::with_name(options::MULTIPLE)
                .short("a")
                .long(options::MULTIPLE)
                .help("support multiple arguments and treat each as a NAME"),
        )
        .arg(Arg::with_name(options::NAME).multiple(true).hidden(true))
        .arg(
            Arg::with_name(options::SUFFIX)
                .short("s")
                .long(options::SUFFIX)
                .value_name("SUFFIX")
                .help("remove a trailing SUFFIX; implies -a"),
        )
        .arg(
            Arg::with_name(options::ZERO)
                .short("z")
                .long(options::ZERO)
                .help("end each output line with NUL, not newline"),
        )
}

fn basename(fullname: &str, suffix: &str) -> String {
    // Remove all platform-specific path separators from the end.
    let path = fullname.trim_end_matches(is_separator);

    // If the path contained *only* suffix characters (for example, if
    // `fullname` were "///" and `suffix` were "/"), then `path` would
    // be left with the empty string. In that case, we set `path` to be
    // the original `fullname` to avoid returning the empty path.
    let path = if path.is_empty() { fullname } else { path };

    // Convert to path buffer and get last path component
    let pb = PathBuf::from(path);
    match pb.components().last() {
        Some(c) => {
            let name = c.as_os_str().to_str().unwrap();
            if name == suffix {
                name.to_string()
            } else {
                name.strip_suffix(suffix).unwrap_or(name).to_string()
            }
        }

        None => "".to_owned(),
    }
}
<|endoftext|>