<commit_before>use std::ops::Range;
use std::sync::Arc;

use im::HashMap;
use itertools::Itertools;

use super::ast::{
    self, Ast, AstError, AstKind, AstString, CollectErrors, Identifier, Int, Lambda, Symbol, Text,
};
use super::cst::{self, Cst, CstDb, CstKind};
use super::error::{CompilerError, CompilerErrorPayload};
use super::rcst_to_cst::RcstToCst;
use crate::compiler::ast::Struct;
use crate::compiler::cst::UnwrapWhitespaceAndComment;
use crate::input::Input;

#[salsa::query_group(CstToAstStorage)]
pub trait CstToAst: CstDb + RcstToCst {
    fn ast_to_cst_id(&self, id: ast::Id) -> Option<cst::Id>;
    fn ast_id_to_span(&self, id: ast::Id) -> Option<Range<usize>>;

    fn cst_to_ast_id(&self, input: Input, id: cst::Id) -> Option<ast::Id>;

    fn ast(&self, input: Input) -> Option<(Arc<Vec<Ast>>, HashMap<ast::Id, cst::Id>)>;
}

fn ast_to_cst_id(db: &dyn CstToAst, id: ast::Id) -> Option<cst::Id> {
    let (_, ast_to_cst_id_mapping) = db.ast(id.input.clone()).unwrap();
    ast_to_cst_id_mapping.get(&id).cloned()
}
fn ast_id_to_span(db: &dyn CstToAst, id: ast::Id) -> Option<Range<usize>> {
    let cst_id = db.ast_to_cst_id(id.clone())?;
    Some(db.find_cst(id.input, cst_id).span)
}

fn cst_to_ast_id(db: &dyn CstToAst, input: Input, id: cst::Id) -> Option<ast::Id> {
    let (_, ast_to_cst_id_mapping) = db.ast(input).unwrap();
    ast_to_cst_id_mapping
        .iter()
        .find_map(|(key, &value)| if value == id { Some(key) } else { None })
        .cloned()
}

fn ast(db: &dyn CstToAst, input: Input) -> Option<(Arc<Vec<Ast>>, HashMap<ast::Id, cst::Id>)> {
    let cst = db.cst(input.clone())?;
    let cst = cst.unwrap_whitespace_and_comment();
    let mut context = LoweringContext::new(input);
    let asts = (&mut context).lower_csts(&cst);
    Some((Arc::new(asts), context.id_mapping))
}

struct LoweringContext {
    input: Input,
    next_id: usize,
    id_mapping: HashMap<ast::Id, cst::Id>,
}
impl LoweringContext {
    fn new(input: Input) -> LoweringContext {
        LoweringContext {
            input,
            next_id: 0,
            id_mapping: HashMap::new(),
        }
    }
    fn lower_csts(&mut self, csts: &[Cst]) -> Vec<Ast> {
        csts.iter().map(|it| self.lower_cst(it)).collect()
    }
    fn lower_cst(&mut self, cst: &Cst) -> Ast {
        match &cst.kind {
            CstKind::EqualsSign
            | CstKind::Comma
            | CstKind::Colon
            | CstKind::OpeningParenthesis
            | CstKind::ClosingParenthesis
            | CstKind::OpeningBracket
            | CstKind::ClosingBracket
            | CstKind::OpeningCurlyBrace
            | CstKind::ClosingCurlyBrace
            | CstKind::Arrow
            | CstKind::DoubleQuote
            | CstKind::Octothorpe => self.create_ast(
                cst.id,
                AstKind::Error {
                    child: None,
                    errors: vec![CompilerError {
                        input: self.input.clone(),
                        span: cst.span.clone(),
                        payload: CompilerErrorPayload::Ast(AstError::UnexpectedPunctuation),
                    }],
                },
            ),
            CstKind::Whitespace(_)
            | CstKind::Newline(_)
            | CstKind::Comment { .. }
            | CstKind::TrailingWhitespace { .. } => {
                panic!("Whitespace should have been removed before lowering to AST.")
            }
            CstKind::Identifier(identifier) => {
                let string = self.create_string_without_id_mapping(identifier.to_string());
                self.create_ast(cst.id, AstKind::Identifier(Identifier(string)))
            }
            CstKind::Symbol(symbol) => {
                let string = self.create_string_without_id_mapping(symbol.to_string());
                self.create_ast(cst.id, AstKind::Symbol(Symbol(string)))
            }
            CstKind::Int { value, .. } => self.create_ast(cst.id, AstKind::Int(Int(*value))),
            CstKind::Text {
                opening_quote,
                parts,
                closing_quote,
            } => {
                assert!(
                    matches!(opening_quote.kind, CstKind::DoubleQuote),
                    "Text needs to start with opening double quote, but started with {}.",
                    opening_quote
                );

                let text = parts
                    .into_iter()
                    .filter_map(|it| match it {
                        Cst {
                            kind: CstKind::TextPart(text),
                            ..
                        } => Some(text),
                        _ => panic!("Text contains non-TextPart. Whitespaces should have been removed already."),
                    })
                    .join("");
                let string = self.create_string_without_id_mapping(text);
                let mut text = self.create_ast(cst.id, AstKind::Text(Text(string)));

                if !matches!(closing_quote.kind, CstKind::DoubleQuote) {
                    text = self.create_ast(
                        closing_quote.id,
                        AstKind::Error {
                            child: Some(Box::new(text)),
                            errors: vec![CompilerError {
                                input: self.input.clone(),
                                span: closing_quote.span.clone(),
                                payload: CompilerErrorPayload::Ast(
                                    AstError::TextWithoutClosingQuote,
                                ),
                            }],
                        },
                    );
                }

                text
            }
            CstKind::TextPart(_) => panic!("TextPart should only occur in Text."),
            CstKind::Parenthesized {
                opening_parenthesis,
                inner,
                closing_parenthesis,
            } => {
                let mut ast = self.lower_cst(inner);

                assert!(
                    matches!(opening_parenthesis.kind, CstKind::OpeningParenthesis),
                    "Parenthesized needs to start with opening parenthesis, but started with {}.",
                    opening_parenthesis
                );
                if !matches!(closing_parenthesis.kind, CstKind::ClosingParenthesis) {
                    ast = self.create_ast(
                        closing_parenthesis.id,
                        AstKind::Error {
                            child: Some(Box::new(ast)),
                            errors: vec![CompilerError {
                                input: self.input.clone(),
                                span: closing_parenthesis.span.clone(),
                                payload: CompilerErrorPayload::Ast(
                                    AstError::ParenthesizedWithoutClosingParenthesis,
                                ),
                            }],
                        },
                    );
                }

                ast
            }
            CstKind::Call { name, arguments } => {
                let name_string = if let CstKind::Identifier(identifier) = &name.kind {
                    Some(self.create_string(name.id.to_owned(), identifier.to_owned()))
                } else {
                    None
                };
                let arguments = self.lower_csts(arguments);

                if let Some(name) = name_string {
                    self.create_ast(cst.id, AstKind::Call(ast::Call { name, arguments }))
                } else {
                    let mut errors = vec![];
                    errors.push(CompilerError {
                        input: self.input.clone(),
                        span: name.span.clone(),
                        payload: CompilerErrorPayload::Ast(AstError::CallOfANonIdentifier),
                    });
                    arguments.collect_errors(&mut errors);
                    self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: None,
                            errors,
                        },
                    )
                }
            }
            CstKind::Struct {
                opening_bracket,
                fields,
                closing_bracket,
            } => {
                let mut errors = vec![];

                assert!(
                    !matches!(opening_bracket.kind, CstKind::OpeningBracket),
                    "Struct should always have an opening bracket, but instead had {}.",
                    opening_bracket
                );

                let fields = fields
                    .into_iter()
                    .filter_map(|field| {
                        if let CstKind::StructField {
                            key,
                            colon,
                            value,
                            comma,
                        } = &field.kind
                        {
                            let mut key = self.lower_cst(&key.clone());
                            let mut value = self.lower_cst(&value.clone());

                            if !matches!(colon.kind, CstKind::Colon) {
                                key = self.create_ast(
                                    colon.id,
                                    AstKind::Error {
                                        child: Some(Box::new(key)),
                                        errors: vec![CompilerError {
                                            input: self.input.clone(),
                                            span: colon.span.clone(),
                                            payload: CompilerErrorPayload::Ast(
                                                AstError::StructKeyWithoutColon,
                                            ),
                                        }],
                                    },
                                )
                            }
                            if let Some(comma) = comma {
                                if !matches!(comma.kind, CstKind::Comma) {
                                    value = self.create_ast(
                                        comma.id,
                                        AstKind::Error {
                                            child: Some(Box::new(value)),
                                            errors: vec![CompilerError {
                                                input: self.input.clone(),
                                                span: comma.span.clone(),
                                                payload: CompilerErrorPayload::Ast(
                                                    AstError::StructValueWithoutComma,
                                                ),
                                            }],
                                        },
                                    )
                                }
                            }

                            Some((key, value))
                        } else {
                            errors.push(CompilerError {
                                input: self.input.clone(),
                                span: cst.span.clone(),
                                payload: CompilerErrorPayload::Ast(
                                    AstError::StructWithNonStructField,
                                ),
                            });
                            None
                        }
                    })
                    .collect();

                if !matches!(closing_bracket.kind, CstKind::ClosingBracket) {
                    errors.push(CompilerError {
                        input: self.input.clone(),
                        span: closing_bracket.span.clone(),
                        payload: CompilerErrorPayload::Ast(AstError::StructWithoutClosingBrace),
                    });
                }

                let ast = self.create_ast(cst.id, AstKind::Struct(Struct { fields }));
                if errors.is_empty() {
                    ast
                } else {
                    self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: Some(Box::new(ast)),
                            errors,
                        },
                    )
                }
            }
            CstKind::StructField { .. } => panic!("StructField should only appear in Struct."),
            CstKind::Lambda {
                opening_curly_brace,
                parameters_and_arrow,
                body,
                closing_curly_brace,
            } => {
                assert!(
                    matches!(opening_curly_brace.kind, CstKind::OpeningCurlyBrace),
                    "Expected an opening curly brace at the beginning of a lambda, but found {}.",
                    opening_curly_brace,
                );

                let (parameters, mut errors) =
                    if let Some((parameters, arrow)) = parameters_and_arrow {
                        assert!(
                            matches!(arrow.kind, CstKind::Arrow),
                            "Expected an arrow after the parameters in a lambda, but found `{}`.",
                            arrow
                        );
                        self.lower_parameters(parameters)
                    } else {
                        (vec![], vec![])
                    };

                let body = self.lower_csts(body);

                if !matches!(closing_curly_brace.kind, CstKind::ClosingCurlyBrace) {
                    errors.push(CompilerError {
                        input: self.input.clone(),
                        span: closing_curly_brace.span.clone(),
                        payload: CompilerErrorPayload::Ast(
                            AstError::LambdaWithoutClosingCurlyBrace,
                        ),
                    });
                }

                let mut ast = self.create_ast(cst.id, AstKind::Lambda(Lambda { parameters, body }));
                if !errors.is_empty() {
                    ast = self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: None,
                            errors,
                        },
                    );
                }
                ast
            }
            CstKind::Assignment {
                name,
                parameters,
                equals_sign,
                body,
            } => {
                let name = self.lower_identifier(name);
                let (parameters, errors) = self.lower_parameters(parameters);

                assert!(
                    matches!(equals_sign.kind, CstKind::EqualsSign),
                    "Expected an equals sign for the assignment, but found {} instead.",
                    equals_sign,
                );

                let mut body = self.lower_csts(body);

                if !parameters.is_empty() {
                    body =
                        vec![self.create_ast(cst.id, AstKind::Lambda(Lambda { parameters, body }))];
                }

                let mut ast =
                    self.create_ast(cst.id, AstKind::Assignment(ast::Assignment { name, body }));
                if !errors.is_empty() {
                    ast = self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: None,
                            errors,
                        },
                    );
                }
                ast
            }
            CstKind::Error { error, .. } => self.create_ast(
                cst.id,
                AstKind::Error {
                    child: None,
                    errors: vec![CompilerError {
                        input: self.input.clone(),
                        span: cst.span.clone(),
                        payload: CompilerErrorPayload::Rcst(error.clone()),
                    }],
                },
            ),
        }
    }

    fn lower_parameters(&mut self, csts: &[Cst]) -> (Vec<AstString>, Vec<CompilerError>) {
        let mut errors = vec![];
        let parameters = csts
            .into_iter()
            .enumerate()
            .map(|(index, it)| match self.lower_parameter(it) {
                Ok(parameter) => parameter,
                Err(error) => {
                    errors.push(error);
                    self.create_string(it.id, format!("<invalid#{}>", index))
                }
            })
            .collect();
        (parameters, errors)
    }
    fn lower_parameter(&mut self, cst: &Cst) -> Result<AstString, CompilerError> {
        if let CstKind::Identifier(identifier) = &cst.kind {
            Ok(self.create_string(cst.id.to_owned(), identifier.clone()))
        } else {
            Err(CompilerError {
                input: self.input.clone(),
                span: cst.span.clone(),
                payload: CompilerErrorPayload::Ast(AstError::ExpectedParameter),
            })
        }
    }
    fn lower_identifier(&mut self, cst: &Cst) -> AstString {
        match cst {
            Cst {
                id,
                kind: CstKind::Identifier(identifier),
                ..
            } => self.create_string(id.to_owned(), identifier.clone()),
            _ => {
                panic!("Expected an identifier, but found `{}`.", cst);
            }
        }
    }

    fn create_ast(&mut self, cst_id: cst::Id, kind: AstKind) -> Ast {
        Ast {
            id: self.create_next_id(cst_id),
            kind,
        }
    }
    fn create_string(&mut self, cst_id: cst::Id, value: String) -> AstString {
        AstString {
            id: self.create_next_id(cst_id),
            value,
        }
    }
    fn create_string_without_id_mapping(&mut self, value: String) -> AstString {
        AstString {
            id: self.create_next_id_without_mapping(),
            value,
        }
    }
    fn create_next_id(&mut self, cst_id: cst::Id) -> ast::Id {
        let id = self.create_next_id_without_mapping();
        assert!(matches!(self.id_mapping.insert(id.clone(), cst_id), None));
        id
    }
    fn create_next_id_without_mapping(&mut self) -> ast::Id {
        let id = ast::Id::new(self.input.clone().clone(), self.next_id);
        self.next_id += 1;
        id
    }
}
<commit_msg>Remove unnecessary clone<commit_after>use std::ops::Range;
use std::sync::Arc;

use im::HashMap;
use itertools::Itertools;

use super::ast::{
    self, Ast, AstError, AstKind, AstString, CollectErrors, Identifier, Int, Lambda, Symbol, Text,
};
use super::cst::{self, Cst, CstDb, CstKind};
use super::error::{CompilerError, CompilerErrorPayload};
use super::rcst_to_cst::RcstToCst;
use crate::compiler::ast::Struct;
use crate::compiler::cst::UnwrapWhitespaceAndComment;
use crate::input::Input;

#[salsa::query_group(CstToAstStorage)]
pub trait CstToAst: CstDb + RcstToCst {
    fn ast_to_cst_id(&self, id: ast::Id) -> Option<cst::Id>;
    fn ast_id_to_span(&self, id: ast::Id) -> Option<Range<usize>>;

    fn cst_to_ast_id(&self, input: Input, id: cst::Id) -> Option<ast::Id>;

    fn ast(&self, input: Input) -> Option<(Arc<Vec<Ast>>, HashMap<ast::Id, cst::Id>)>;
}

fn ast_to_cst_id(db: &dyn CstToAst, id: ast::Id) -> Option<cst::Id> {
    let (_, ast_to_cst_id_mapping) = db.ast(id.input.clone()).unwrap();
    ast_to_cst_id_mapping.get(&id).cloned()
}
fn ast_id_to_span(db: &dyn CstToAst, id: ast::Id) -> Option<Range<usize>> {
    let cst_id = db.ast_to_cst_id(id.clone())?;
    Some(db.find_cst(id.input, cst_id).span)
}

fn cst_to_ast_id(db: &dyn CstToAst, input: Input, id: cst::Id) -> Option<ast::Id> {
    let (_, ast_to_cst_id_mapping) = db.ast(input).unwrap();
    ast_to_cst_id_mapping
        .iter()
        .find_map(|(key, &value)| if value == id { Some(key) } else { None })
        .cloned()
}

fn ast(db: &dyn CstToAst, input: Input) -> Option<(Arc<Vec<Ast>>, HashMap<ast::Id, cst::Id>)> {
    let cst = db.cst(input.clone())?;
    let cst = cst.unwrap_whitespace_and_comment();
    let mut context = LoweringContext::new(input);
    let asts = (&mut context).lower_csts(&cst);
    Some((Arc::new(asts), context.id_mapping))
}

struct LoweringContext {
    input: Input,
    next_id: usize,
    id_mapping: HashMap<ast::Id, cst::Id>,
}
impl LoweringContext {
    fn new(input: Input) -> LoweringContext {
        LoweringContext {
            input,
            next_id: 0,
            id_mapping: HashMap::new(),
        }
    }
    fn lower_csts(&mut self, csts: &[Cst]) -> Vec<Ast> {
        csts.iter().map(|it| self.lower_cst(it)).collect()
    }
    fn lower_cst(&mut self, cst: &Cst) -> Ast {
        match &cst.kind {
            CstKind::EqualsSign
            | CstKind::Comma
            | CstKind::Colon
            | CstKind::OpeningParenthesis
            | CstKind::ClosingParenthesis
            | CstKind::OpeningBracket
            | CstKind::ClosingBracket
            | CstKind::OpeningCurlyBrace
            | CstKind::ClosingCurlyBrace
            | CstKind::Arrow
            | CstKind::DoubleQuote
            | CstKind::Octothorpe => self.create_ast(
                cst.id,
                AstKind::Error {
                    child: None,
                    errors: vec![CompilerError {
                        input: self.input.clone(),
                        span: cst.span.clone(),
                        payload: CompilerErrorPayload::Ast(AstError::UnexpectedPunctuation),
                    }],
                },
            ),
            CstKind::Whitespace(_)
            | CstKind::Newline(_)
            | CstKind::Comment { .. }
            | CstKind::TrailingWhitespace { .. } => {
                panic!("Whitespace should have been removed before lowering to AST.")
            }
            CstKind::Identifier(identifier) => {
                let string = self.create_string_without_id_mapping(identifier.to_string());
                self.create_ast(cst.id, AstKind::Identifier(Identifier(string)))
            }
            CstKind::Symbol(symbol) => {
                let string = self.create_string_without_id_mapping(symbol.to_string());
                self.create_ast(cst.id, AstKind::Symbol(Symbol(string)))
            }
            CstKind::Int { value, .. } => self.create_ast(cst.id, AstKind::Int(Int(*value))),
            CstKind::Text {
                opening_quote,
                parts,
                closing_quote,
            } => {
                assert!(
                    matches!(opening_quote.kind, CstKind::DoubleQuote),
                    "Text needs to start with opening double quote, but started with {}.",
                    opening_quote
                );

                let text = parts
                    .into_iter()
                    .filter_map(|it| match it {
                        Cst {
                            kind: CstKind::TextPart(text),
                            ..
                        } => Some(text),
                        _ => panic!("Text contains non-TextPart. Whitespaces should have been removed already."),
                    })
                    .join("");
                let string = self.create_string_without_id_mapping(text);
                let mut text = self.create_ast(cst.id, AstKind::Text(Text(string)));

                if !matches!(closing_quote.kind, CstKind::DoubleQuote) {
                    text = self.create_ast(
                        closing_quote.id,
                        AstKind::Error {
                            child: Some(Box::new(text)),
                            errors: vec![CompilerError {
                                input: self.input.clone(),
                                span: closing_quote.span.clone(),
                                payload: CompilerErrorPayload::Ast(
                                    AstError::TextWithoutClosingQuote,
                                ),
                            }],
                        },
                    );
                }

                text
            }
            CstKind::TextPart(_) => panic!("TextPart should only occur in Text."),
            CstKind::Parenthesized {
                opening_parenthesis,
                inner,
                closing_parenthesis,
            } => {
                let mut ast = self.lower_cst(inner);

                assert!(
                    matches!(opening_parenthesis.kind, CstKind::OpeningParenthesis),
                    "Parenthesized needs to start with opening parenthesis, but started with {}.",
                    opening_parenthesis
                );
                if !matches!(closing_parenthesis.kind, CstKind::ClosingParenthesis) {
                    ast = self.create_ast(
                        closing_parenthesis.id,
                        AstKind::Error {
                            child: Some(Box::new(ast)),
                            errors: vec![CompilerError {
                                input: self.input.clone(),
                                span: closing_parenthesis.span.clone(),
                                payload: CompilerErrorPayload::Ast(
                                    AstError::ParenthesizedWithoutClosingParenthesis,
                                ),
                            }],
                        },
                    );
                }

                ast
            }
            CstKind::Call { name, arguments } => {
                let name_string = if let CstKind::Identifier(identifier) = &name.kind {
                    Some(self.create_string(name.id.to_owned(), identifier.to_owned()))
                } else {
                    None
                };
                let arguments = self.lower_csts(arguments);

                if let Some(name) = name_string {
                    self.create_ast(cst.id, AstKind::Call(ast::Call { name, arguments }))
                } else {
                    let mut errors = vec![];
                    errors.push(CompilerError {
                        input: self.input.clone(),
                        span: name.span.clone(),
                        payload: CompilerErrorPayload::Ast(AstError::CallOfANonIdentifier),
                    });
                    arguments.collect_errors(&mut errors);
                    self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: None,
                            errors,
                        },
                    )
                }
            }
            CstKind::Struct {
                opening_bracket,
                fields,
                closing_bracket,
            } => {
                let mut errors = vec![];

                assert!(
                    !matches!(opening_bracket.kind, CstKind::OpeningBracket),
                    "Struct should always have an opening bracket, but instead had {}.",
                    opening_bracket
                );

                let fields = fields
                    .into_iter()
                    .filter_map(|field| {
                        if let CstKind::StructField {
                            key,
                            colon,
                            value,
                            comma,
                        } = &field.kind
                        {
                            let mut key = self.lower_cst(&key.clone());
                            let mut value = self.lower_cst(&value.clone());

                            if !matches!(colon.kind, CstKind::Colon) {
                                key = self.create_ast(
                                    colon.id,
                                    AstKind::Error {
                                        child: Some(Box::new(key)),
                                        errors: vec![CompilerError {
                                            input: self.input.clone(),
                                            span: colon.span.clone(),
                                            payload: CompilerErrorPayload::Ast(
                                                AstError::StructKeyWithoutColon,
                                            ),
                                        }],
                                    },
                                )
                            }
                            if let Some(comma) = comma {
                                if !matches!(comma.kind, CstKind::Comma) {
                                    value = self.create_ast(
                                        comma.id,
                                        AstKind::Error {
                                            child: Some(Box::new(value)),
                                            errors: vec![CompilerError {
                                                input: self.input.clone(),
                                                span: comma.span.clone(),
                                                payload: CompilerErrorPayload::Ast(
                                                    AstError::StructValueWithoutComma,
                                                ),
                                            }],
                                        },
                                    )
                                }
                            }

                            Some((key, value))
                        } else {
                            errors.push(CompilerError {
                                input: self.input.clone(),
                                span: cst.span.clone(),
                                payload: CompilerErrorPayload::Ast(
                                    AstError::StructWithNonStructField,
                                ),
                            });
                            None
                        }
                    })
                    .collect();

                if !matches!(closing_bracket.kind, CstKind::ClosingBracket) {
                    errors.push(CompilerError {
                        input: self.input.clone(),
                        span: closing_bracket.span.clone(),
                        payload: CompilerErrorPayload::Ast(AstError::StructWithoutClosingBrace),
                    });
                }

                let ast = self.create_ast(cst.id, AstKind::Struct(Struct { fields }));
                if errors.is_empty() {
                    ast
                } else {
                    self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: Some(Box::new(ast)),
                            errors,
                        },
                    )
                }
            }
            CstKind::StructField { .. } => panic!("StructField should only appear in Struct."),
            CstKind::Lambda {
                opening_curly_brace,
                parameters_and_arrow,
                body,
                closing_curly_brace,
            } => {
                assert!(
                    matches!(opening_curly_brace.kind, CstKind::OpeningCurlyBrace),
                    "Expected an opening curly brace at the beginning of a lambda, but found {}.",
                    opening_curly_brace,
                );

                let (parameters, mut errors) =
                    if let Some((parameters, arrow)) = parameters_and_arrow {
                        assert!(
                            matches!(arrow.kind, CstKind::Arrow),
                            "Expected an arrow after the parameters in a lambda, but found `{}`.",
                            arrow
                        );
                        self.lower_parameters(parameters)
                    } else {
                        (vec![], vec![])
                    };

                let body = self.lower_csts(body);

                if !matches!(closing_curly_brace.kind, CstKind::ClosingCurlyBrace) {
                    errors.push(CompilerError {
                        input: self.input.clone(),
                        span: closing_curly_brace.span.clone(),
                        payload: CompilerErrorPayload::Ast(
                            AstError::LambdaWithoutClosingCurlyBrace,
                        ),
                    });
                }

                let mut ast = self.create_ast(cst.id, AstKind::Lambda(Lambda { parameters, body }));
                if !errors.is_empty() {
                    ast = self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: None,
                            errors,
                        },
                    );
                }
                ast
            }
            CstKind::Assignment {
                name,
                parameters,
                equals_sign,
                body,
            } => {
                let name = self.lower_identifier(name);
                let (parameters, errors) = self.lower_parameters(parameters);

                assert!(
                    matches!(equals_sign.kind, CstKind::EqualsSign),
                    "Expected an equals sign for the assignment, but found {} instead.",
                    equals_sign,
                );

                let mut body = self.lower_csts(body);

                if !parameters.is_empty() {
                    body =
                        vec![self.create_ast(cst.id, AstKind::Lambda(Lambda { parameters, body }))];
                }

                let mut ast =
                    self.create_ast(cst.id, AstKind::Assignment(ast::Assignment { name, body }));
                if !errors.is_empty() {
                    ast = self.create_ast(
                        cst.id,
                        AstKind::Error {
                            child: None,
                            errors,
                        },
                    );
                }
                ast
            }
            CstKind::Error { error, .. } => self.create_ast(
                cst.id,
                AstKind::Error {
                    child: None,
                    errors: vec![CompilerError {
                        input: self.input.clone(),
                        span: cst.span.clone(),
                        payload: CompilerErrorPayload::Rcst(error.clone()),
                    }],
                },
            ),
        }
    }

    fn lower_parameters(&mut self, csts: &[Cst]) -> (Vec<AstString>, Vec<CompilerError>) {
        let mut errors = vec![];
        let parameters = csts
            .into_iter()
            .enumerate()
            .map(|(index, it)| match self.lower_parameter(it) {
                Ok(parameter) => parameter,
                Err(error) => {
                    errors.push(error);
                    self.create_string(it.id, format!("<invalid#{}>", index))
                }
            })
            .collect();
        (parameters, errors)
    }
    fn lower_parameter(&mut self, cst: &Cst) -> Result<AstString, CompilerError> {
        if let CstKind::Identifier(identifier) = &cst.kind {
            Ok(self.create_string(cst.id.to_owned(), identifier.clone()))
        } else {
            Err(CompilerError {
                input: self.input.clone(),
                span: cst.span.clone(),
                payload: CompilerErrorPayload::Ast(AstError::ExpectedParameter),
            })
        }
    }
    fn lower_identifier(&mut self, cst: &Cst) -> AstString {
        match cst {
            Cst {
                id,
                kind: CstKind::Identifier(identifier),
                ..
            } => self.create_string(id.to_owned(), identifier.clone()),
            _ => {
                panic!("Expected an identifier, but found `{}`.", cst);
            }
        }
    }

    fn create_ast(&mut self, cst_id: cst::Id, kind: AstKind) -> Ast {
        Ast {
            id: self.create_next_id(cst_id),
            kind,
        }
    }
    fn create_string(&mut self, cst_id: cst::Id, value: String) -> AstString {
        AstString {
            id: self.create_next_id(cst_id),
            value,
        }
    }
    fn create_string_without_id_mapping(&mut self, value: String) -> AstString {
        AstString {
            id: self.create_next_id_without_mapping(),
            value,
        }
    }
    fn create_next_id(&mut self, cst_id: cst::Id) -> ast::Id {
        let id = self.create_next_id_without_mapping();
        assert!(matches!(self.id_mapping.insert(id.clone(), cst_id), None));
        id
    }
    fn create_next_id_without_mapping(&mut self) -> ast::Id {
        let id = ast::Id::new(self.input.clone(), self.next_id);
        self.next_id += 1;
        id
    }
}
<|endoftext|>


<commit_before>// src/common/utilities/url.rs

/// Utilities for URLs

// Import
// External
use ::regex::Regex;

#[derive(Debug)]
pub struct SortParam{
    pub field: String,
    pub direction: i32
}

/// Get Sort Param from URL string
///
/// # Arguments
/// * `sort` - A String slice of the "sort" property of a URL query String
/// sort string is expected to match the following regex: ([\+-]?)([^\|]+)
/// Examples: "date", "-date", "date|-name"
///
/// # Returns
/// A Vector of `SortParam`s
pub fn get_sort_params(sort: &str) -> Vec<SortParam>{
    let mut sort_params = Vec::new();
    let re = Regex::new(r"(?P<direction>[\+-]?)(?P<field>[^\|]+)").unwrap();
    for caps in re.captures_iter(sort) {
        let mut direction = 1;
        let mut field = String::new();
        if let Some(dir) = caps.name("direction"){
            if dir == "-"{
                direction = -1;
            }
        }
        if let Some(fld) = caps.name("field"){
            field = fld.to_owned();
        }
        sort_params.push(SortParam{
            field: field,
            direction: direction
        });
    }

    sort_params
}
<commit_msg>Add test todo<commit_after>// src/common/utilities/url.rs

/// Utilities for URLs

// Import
// External
use ::regex::Regex;

#[derive(Debug)]
pub struct SortParam{
    pub field: String,
    pub direction: i32
}

/// Get Sort Param from URL string
///
/// # Arguments
/// * `sort` - A String slice of the "sort" property of a URL query String
/// sort string is expected to match the following regex: ([\+-]?)([^\|]+)
/// Examples: "date", "-date", "date|-name"
///
/// # Returns
/// A Vector of `SortParam`s
///
/// TODO: Add documentation test
pub fn get_sort_params(sort: &str) -> Vec<SortParam>{
    let mut sort_params = Vec::new();
    let re = Regex::new(r"(?P<direction>[\+-]?)(?P<field>[^\|]+)").unwrap();
    for caps in re.captures_iter(sort) {
        let mut direction = 1;
        let mut field = String::new();
        if let Some(dir) = caps.name("direction"){
            if dir == "-"{
                direction = -1;
            }
        }
        if let Some(fld) = caps.name("field"){
            field = fld.to_owned();
        }
        sort_params.push(SortParam{
            field: field,
            direction: direction
        });
    }

    sort_params
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 Johannes Köster, Peer Aramillo Irizar.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of alphabets and useful utilities.
//!
//! # Example
//!
//! ```rust
//! use bio::alphabets;
//! let alphabet = alphabets::dna::alphabet();
//! assert!(alphabet.is_word(b"AACCTgga"));
//! assert!(!alphabet.is_word(b"AXYZ"));
//! ```

use std::borrow::Borrow;
use std::mem;

use bit_set::BitSet;
use vec_map::VecMap;

pub mod dna;
pub mod protein;
pub mod rna;

pub type SymbolRanks = VecMap<u8>;

/// Representation of an alphabet.
#[derive(Debug, PartialEq)]
pub struct Alphabet {
    pub symbols: BitSet,
}

impl Alphabet {
    /// Create new alphabet from given symbols.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// // Create an alphabet (note that a DNA alphabet is already available in bio::alphabets::dna).
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// // Check whether a given text is a word over the alphabet.
    /// assert!(dna_alphabet.is_word(b"GAttACA"));
    /// ```
    pub fn new<C, T>(symbols: T) -> Self
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        let mut s = BitSet::new();
        s.extend(symbols.into_iter().map(|c| *c.borrow() as usize));

        Alphabet { symbols: s }
    }

    /// Insert symbol into alphabet.
    ///
    /// Complexity: O(1)
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let mut dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// assert!(!dna_alphabet.is_word(b"N"));
    /// dna_alphabet.insert(78);
    /// assert!(dna_alphabet.is_word(b"N"));
    /// ```
    pub fn insert(&mut self, a: u8) {
        self.symbols.insert(a as usize);
    }

    /// Check if given text is a word over the alphabet.
    ///
    /// Complexity: O(n), where n is the length of the text.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// assert!(dna_alphabet.is_word(b"GAttACA"));
    /// assert!(!dna_alphabet.is_word(b"42"));
    /// ```
    pub fn is_word<C, T>(&self, text: T) -> bool
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        text.into_iter()
            .all(|c| self.symbols.contains(*c.borrow() as usize))
    }

    /// Return lexicographically maximal symbol.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// assert_eq!(dna_alphabet.max_symbol(), Some(116)); // max symbol is "t"
    /// let empty_alphabet = alphabets::Alphabet::new(b"");
    /// assert_eq!(empty_alphabet.max_symbol(), None);
    /// ```
    pub fn max_symbol(&self) -> Option<u8> {
        self.symbols.iter().max().map(|a| a as u8)
    }

    /// Return size of the alphabet.
    ///
    /// Upper and lower case representations of the same character
    /// are counted as distinct characters.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// assert_eq!(dna_alphabet.len(), 8);
    /// ```
    pub fn len(&self) -> usize {
        self.symbols.len()
    }

    /// Is this alphabet empty?
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// assert!(!dna_alphabet.is_empty());
    /// let empty_alphabet = alphabets::Alphabet::new(b"");
    /// assert!(empty_alphabet.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.symbols.is_empty()
    }
}

/// Tools based on transforming the alphabet symbols to their lexicographical ranks.
///
/// Lexicographical rank is computed using `u8` representations,
/// i.e. ASCII codes, of the input characters.
/// For example, assuming that the alphabet consists of the symbols `A`, `C`, `G`, and `T`, this
/// will yield ranks `0`, `1`, `2`, `3` for them, respectively.
///
/// `RankTransform` can be used in to perform bit encoding for texts over a
/// given alphabet via `bio::data_structures::bitenc`.
#[derive(Serialize, Deserialize)]
pub struct RankTransform {
    pub ranks: SymbolRanks,
}

impl RankTransform {
    /// Construct a new `RankTransform`.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// ```
    pub fn new(alphabet: &Alphabet) -> Self {
        let mut ranks = VecMap::new();
        for (r, c) in alphabet.symbols.iter().enumerate() {
            ranks.insert(c, r as u8);
        }

        RankTransform { ranks }
    }

    /// Get the rank of symbol `a`.
    ///
    /// This method panics for characters not contained in the alphabet.
    ///
    /// Complexity: O(1)
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// assert_eq!(dna_ranks.get(65), 0); // "A"
    /// assert_eq!(dna_ranks.get(116), 7); // "t"
    /// ```
    pub fn get(&self, a: u8) -> u8 {
        *self.ranks.get(a as usize).expect("Unexpected character.")
    }

    /// Transform a given `text` into a vector of rank values.
    ///
    /// Complexity: O(n), where n is the length of the text.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// let text = b"aAcCgGtT";
    /// assert_eq!(dna_ranks.transform(text), vec![4, 0, 5, 1, 6, 2, 7, 3]);
    /// ```
    pub fn transform<C, T>(&self, text: T) -> Vec<u8>
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        text.into_iter()
            .map(|c| {
                *self
                    .ranks
                    .get(*c.borrow() as usize)
                    .expect("Unexpected character in text.")
            })
            .collect()
    }

    /// Iterate over q-grams (substrings of length q) of given `text`. The q-grams are encoded
    /// as `usize` by storing the symbol ranks in log2(|A|) bits (with |A| being the alphabet size).
    ///
    /// If q is larger than usize::BITS / log2(|A|), this method fails with an assertion.
    ///
    /// Complexity: O(n), where n is the length of the text.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    ///
    /// let q_grams: Vec<usize> = dna_ranks.qgrams(2, b"ACGT").collect();
    /// assert_eq!(q_grams, vec![1, 10, 19]);
    /// ```
    pub fn qgrams<C, T>(&self, q: u32, text: T) -> QGrams<'_, C, T::IntoIter>
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        let bits = (self.ranks.len() as f32).log2().ceil() as u32;
        assert!(
            (bits * q) as usize <= mem::size_of::<usize>() * 8,
            "Expecting q to be smaller than usize / log2(|A|)"
        );

        let mut qgrams = QGrams {
            text: text.into_iter(),
            ranks: self,
            bits,
            mask: (1 << (q * bits)) - 1,
            qgram: 0,
        };

        for _ in 0..q - 1 {
            qgrams.next();
        }

        qgrams
    }

    /// Restore alphabet from transform.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// assert_eq!(dna_ranks.alphabet().symbols, dna_alphabet.symbols);
    /// ```
    pub fn alphabet(&self) -> Alphabet {
        let mut symbols = BitSet::with_capacity(self.ranks.len());
        symbols.extend(self.ranks.keys());
        Alphabet { symbols }
    }

    /// Compute the number of bits required to encode the largest rank value.
    ///
    /// For example, the alphabet `b"ACGT"` with 4 symbols has the maximal rank
    /// 3, which can be encoded in 2 bits.
    ///
    /// This value can be used to create a `data_structures::bitenc::BitEnc`
    /// bit encoding tailored to the given alphabet.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// assert_eq!(dna_ranks.get_width(), 2);
    /// let dna_n_alphabet = alphabets::Alphabet::new(b"ACGTN");
    /// let dna_n_ranks = alphabets::RankTransform::new(&dna_n_alphabet);
    /// assert_eq!(dna_n_ranks.get_width(), 3);
    /// ```
    pub fn get_width(&self) -> usize {
        (self.ranks.len() as f32).log2().ceil() as usize
    }
}

/// Iterator over q-grams.
pub struct QGrams<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    text: T,
    ranks: &'a RankTransform,
    bits: u32,
    mask: usize,
    qgram: usize,
}

impl<'a, C, T> QGrams<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    /// Push a new character into the current qgram.
    fn qgram_push(&mut self, a: u8) {
        self.qgram <<= self.bits;
        self.qgram |= a as usize;
        self.qgram &= self.mask;
    }
}

impl<'a, C, T> Iterator for QGrams<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        match self.text.next() {
            Some(a) => {
                let b = self.ranks.get(*a.borrow());
                self.qgram_push(b);
                Some(self.qgram)
            }
            None => None,
        }
    }
}

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

    #[test]
    fn test_alphabet_eq() {
        assert_eq!(Alphabet::new(b"ATCG"), Alphabet::new(b"ATCG"));
        assert_eq!(Alphabet::new(b"ATCG"), Alphabet::new(b"TAGC"));
        assert_ne!(Alphabet::new(b"ATCG"), Alphabet::new(b"ATC"));
    }
}
<commit_msg>Adds niceties for taking union/intersect/difference on alphabets. (#385)<commit_after>// Copyright 2014-2015 Johannes Köster, Peer Aramillo Irizar.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of alphabets and useful utilities.
//!
//! # Example
//!
//! ```rust
//! use bio::alphabets;
//! let alphabet = alphabets::dna::alphabet();
//! assert!(alphabet.is_word(b"AACCTgga"));
//! assert!(!alphabet.is_word(b"AXYZ"));
//! ```

use std::borrow::Borrow;
use std::mem;

use bit_set::BitSet;
use vec_map::VecMap;

pub mod dna;
pub mod protein;
pub mod rna;

pub type SymbolRanks = VecMap<u8>;

/// Representation of an alphabet.
#[derive(Debug, PartialEq)]
pub struct Alphabet {
    pub symbols: BitSet,
}

impl Alphabet {
    /// Create new alphabet from given symbols.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// // Create an alphabet (note that a DNA alphabet is already available in bio::alphabets::dna).
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// // Check whether a given text is a word over the alphabet.
    /// assert!(dna_alphabet.is_word(b"GAttACA"));
    /// ```
    pub fn new<C, T>(symbols: T) -> Self
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        let mut s = BitSet::new();
        s.extend(symbols.into_iter().map(|c| *c.borrow() as usize));

        Alphabet { symbols: s }
    }

    /// Insert symbol into alphabet.
    ///
    /// Complexity: O(1)
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let mut dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// assert!(!dna_alphabet.is_word(b"N"));
    /// dna_alphabet.insert(78);
    /// assert!(dna_alphabet.is_word(b"N"));
    /// ```
    pub fn insert(&mut self, a: u8) {
        self.symbols.insert(a as usize);
    }

    /// Check if given text is a word over the alphabet.
    ///
    /// Complexity: O(n), where n is the length of the text.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// assert!(dna_alphabet.is_word(b"GAttACA"));
    /// assert!(!dna_alphabet.is_word(b"42"));
    /// ```
    pub fn is_word<C, T>(&self, text: T) -> bool
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        text.into_iter()
            .all(|c| self.symbols.contains(*c.borrow() as usize))
    }

    /// Return lexicographically maximal symbol.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// assert_eq!(dna_alphabet.max_symbol(), Some(116)); // max symbol is "t"
    /// let empty_alphabet = alphabets::Alphabet::new(b"");
    /// assert_eq!(empty_alphabet.max_symbol(), None);
    /// ```
    pub fn max_symbol(&self) -> Option<u8> {
        self.symbols.iter().max().map(|a| a as u8)
    }

    /// Return size of the alphabet.
    ///
    /// Upper and lower case representations of the same character
    /// are counted as distinct characters.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// assert_eq!(dna_alphabet.len(), 8);
    /// ```
    pub fn len(&self) -> usize {
        self.symbols.len()
    }

    /// Is this alphabet empty?
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// assert!(!dna_alphabet.is_empty());
    /// let empty_alphabet = alphabets::Alphabet::new(b"");
    /// assert!(empty_alphabet.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.symbols.is_empty()
    }

    /// Return a new alphabet taking the intersect between this and other.
    ///
    /// # Example
    /// ```
    /// use bio::alphabets;
    ///
    /// let alpha_a = alphabets::Alphabet::new(b"acgtACGT");
    /// let alpha_b = alphabets::Alphabet::new(b"atcgMVP");
    /// let intersect_alpha = alpha_a.intersection(&alpha_b);
    ///
    /// assert_eq!(intersect_alpha, alphabets::Alphabet::new(b"atcg"));
    /// ```
    pub fn intersection(&self, other: &Alphabet) -> Self {
        return Alphabet {
            symbols: self.symbols.intersection(&other.symbols).collect(),
        };
    }

    /// Return a new alphabet taking the difference between this and other.
    ///
    /// # Example
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// let dna_alphabet_upper = alphabets::Alphabet::new(b"ACGT");
    /// let dna_lower = dna_alphabet.difference(&dna_alphabet_upper);
    ///
    /// assert_eq!(dna_lower, alphabets::Alphabet::new(b"atcg"));
    /// ```
    pub fn difference(&self, other: &Alphabet) -> Self {
        return Alphabet {
            symbols: self.symbols.difference(&other.symbols).collect(),
        };
    }

    /// Return a new alphabet taking the union between this and other.
    ///
    /// # Example
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ATCG");
    /// let tokenize_alpha = alphabets::Alphabet::new(b"?|");
    /// let alpha = dna_alphabet.union(&tokenize_alpha);
    ///
    /// assert_eq!(alpha, alphabets::Alphabet::new(b"ATCG?|"));
    /// ```
    pub fn union(&self, other: &Alphabet) -> Self {
        return Alphabet {
            symbols: self.symbols.union(&other.symbols).collect(),
        };
    }
}

/// Tools based on transforming the alphabet symbols to their lexicographical ranks.
///
/// Lexicographical rank is computed using `u8` representations,
/// i.e. ASCII codes, of the input characters.
/// For example, assuming that the alphabet consists of the symbols `A`, `C`, `G`, and `T`, this
/// will yield ranks `0`, `1`, `2`, `3` for them, respectively.
///
/// `RankTransform` can be used in to perform bit encoding for texts over a
/// given alphabet via `bio::data_structures::bitenc`.
#[derive(Serialize, Deserialize)]
pub struct RankTransform {
    pub ranks: SymbolRanks,
}

impl RankTransform {
    /// Construct a new `RankTransform`.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// ```
    pub fn new(alphabet: &Alphabet) -> Self {
        let mut ranks = VecMap::new();
        for (r, c) in alphabet.symbols.iter().enumerate() {
            ranks.insert(c, r as u8);
        }

        RankTransform { ranks }
    }

    /// Get the rank of symbol `a`.
    ///
    /// This method panics for characters not contained in the alphabet.
    ///
    /// Complexity: O(1)
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// assert_eq!(dna_ranks.get(65), 0); // "A"
    /// assert_eq!(dna_ranks.get(116), 7); // "t"
    /// ```
    pub fn get(&self, a: u8) -> u8 {
        *self.ranks.get(a as usize).expect("Unexpected character.")
    }

    /// Transform a given `text` into a vector of rank values.
    ///
    /// Complexity: O(n), where n is the length of the text.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// let text = b"aAcCgGtT";
    /// assert_eq!(dna_ranks.transform(text), vec![4, 0, 5, 1, 6, 2, 7, 3]);
    /// ```
    pub fn transform<C, T>(&self, text: T) -> Vec<u8>
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        text.into_iter()
            .map(|c| {
                *self
                    .ranks
                    .get(*c.borrow() as usize)
                    .expect("Unexpected character in text.")
            })
            .collect()
    }

    /// Iterate over q-grams (substrings of length q) of given `text`. The q-grams are encoded
    /// as `usize` by storing the symbol ranks in log2(|A|) bits (with |A| being the alphabet size).
    ///
    /// If q is larger than usize::BITS / log2(|A|), this method fails with an assertion.
    ///
    /// Complexity: O(n), where n is the length of the text.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGTacgt");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    ///
    /// let q_grams: Vec<usize> = dna_ranks.qgrams(2, b"ACGT").collect();
    /// assert_eq!(q_grams, vec![1, 10, 19]);
    /// ```
    pub fn qgrams<C, T>(&self, q: u32, text: T) -> QGrams<'_, C, T::IntoIter>
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        let bits = (self.ranks.len() as f32).log2().ceil() as u32;
        assert!(
            (bits * q) as usize <= mem::size_of::<usize>() * 8,
            "Expecting q to be smaller than usize / log2(|A|)"
        );

        let mut qgrams = QGrams {
            text: text.into_iter(),
            ranks: self,
            bits,
            mask: (1 << (q * bits)) - 1,
            qgram: 0,
        };

        for _ in 0..q - 1 {
            qgrams.next();
        }

        qgrams
    }

    /// Restore alphabet from transform.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"acgtACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// assert_eq!(dna_ranks.alphabet().symbols, dna_alphabet.symbols);
    /// ```
    pub fn alphabet(&self) -> Alphabet {
        let mut symbols = BitSet::with_capacity(self.ranks.len());
        symbols.extend(self.ranks.keys());
        Alphabet { symbols }
    }

    /// Compute the number of bits required to encode the largest rank value.
    ///
    /// For example, the alphabet `b"ACGT"` with 4 symbols has the maximal rank
    /// 3, which can be encoded in 2 bits.
    ///
    /// This value can be used to create a `data_structures::bitenc::BitEnc`
    /// bit encoding tailored to the given alphabet.
    ///
    /// Complexity: O(n), where n is the number of symbols in the alphabet.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::alphabets;
    ///
    /// let dna_alphabet = alphabets::Alphabet::new(b"ACGT");
    /// let dna_ranks = alphabets::RankTransform::new(&dna_alphabet);
    /// assert_eq!(dna_ranks.get_width(), 2);
    /// let dna_n_alphabet = alphabets::Alphabet::new(b"ACGTN");
    /// let dna_n_ranks = alphabets::RankTransform::new(&dna_n_alphabet);
    /// assert_eq!(dna_n_ranks.get_width(), 3);
    /// ```
    pub fn get_width(&self) -> usize {
        (self.ranks.len() as f32).log2().ceil() as usize
    }
}

/// Iterator over q-grams.
pub struct QGrams<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    text: T,
    ranks: &'a RankTransform,
    bits: u32,
    mask: usize,
    qgram: usize,
}

impl<'a, C, T> QGrams<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    /// Push a new character into the current qgram.
    fn qgram_push(&mut self, a: u8) {
        self.qgram <<= self.bits;
        self.qgram |= a as usize;
        self.qgram &= self.mask;
    }
}

impl<'a, C, T> Iterator for QGrams<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        match self.text.next() {
            Some(a) => {
                let b = self.ranks.get(*a.borrow());
                self.qgram_push(b);
                Some(self.qgram)
            }
            None => None,
        }
    }
}

/// Returns the english ascii lower case alphabet.
pub fn english_ascii_lower_alphabet() -> Alphabet {
    Alphabet::new(&b"abcdefghijklmnopqrstuvwxyz"[..])
}

/// Returns the english ascii upper case alphabet.
pub fn english_ascii_upper_alphabet() -> Alphabet {
    Alphabet::new(&b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[..])
}

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

    #[test]
    fn test_alphabet_eq() {
        assert_eq!(Alphabet::new(b"ATCG"), Alphabet::new(b"ATCG"));
        assert_eq!(Alphabet::new(b"ATCG"), Alphabet::new(b"TAGC"));
        assert_ne!(Alphabet::new(b"ATCG"), Alphabet::new(b"ATC"));
    }
}
<|endoftext|>


<commit_before>use crate::alloc::{Allocator, Global};
use crate::raw_vec::RawVec;
use core::fmt;
use core::intrinsics::arith_offset;
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen};
use core::marker::PhantomData;
use core::mem::{self};
use core::ptr::{self, NonNull};
use core::slice::{self};

/// An iterator that moves out of a vector.
///
/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec)
/// (provided by the [`IntoIterator`] trait).
///
/// # Example
///
/// ```
/// let v = vec![0, 1, 2];
/// let iter: std::vec::IntoIter<_> = v.into_iter();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<
    T,
    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
    pub(super) buf: NonNull<T>,
    pub(super) phantom: PhantomData<T>,
    pub(super) cap: usize,
    pub(super) alloc: A,
    pub(super) ptr: *const T,
    pub(super) end: *const T,
}

#[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}

impl<T, A: Allocator> IntoIter<T, A> {
    /// Returns the remaining items of this iterator as a slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// let _ = into_iter.next().unwrap();
    /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_slice(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.ptr, self.len()) }
    }

    /// Returns the remaining items of this iterator as a mutable slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// into_iter.as_mut_slice()[2] = 'z';
    /// assert_eq!(into_iter.next().unwrap(), 'a');
    /// assert_eq!(into_iter.next().unwrap(), 'b');
    /// assert_eq!(into_iter.next().unwrap(), 'z');
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        unsafe { &mut *self.as_raw_mut_slice() }
    }

    /// Returns a reference to the underlying allocator.
    #[unstable(feature = "allocator_api", issue = "32838")]
    #[inline]
    pub fn allocator(&self) -> &A {
        &self.alloc
    }

    fn as_raw_mut_slice(&mut self) -> *mut [T] {
        ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
    }

    /// Drops remaining elements and relinquishes the backing allocation.
    ///
    /// This is roughly equivalent to the following, but more efficient
    ///
    /// ```
    /// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter();
    /// (&mut into_iter).for_each(core::mem::drop);
    /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); }
    /// ```
    #[cfg(not(no_global_oom_handling))]
    pub(super) fn forget_allocation_drop_remaining(&mut self) {
        let remaining = self.as_raw_mut_slice();

        // overwrite the individual fields instead of creating a new
        // struct and then overwriting &mut self.
        // this creates less assembly
        self.cap = 0;
        self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
        self.ptr = self.buf.as_ptr();
        self.end = self.buf.as_ptr();

        unsafe {
            ptr::drop_in_place(remaining);
        }
    }
}

#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
impl<T, A: Allocator> AsRef<[T]> for IntoIter<T, A> {
    fn as_ref(&self) -> &[T] {
        self.as_slice()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Sync, A: Allocator> Sync for IntoIter<T, A> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.ptr as *const _ == self.end {
            None
        } else if mem::size_of::<T>() == 0 {
            // purposefully don't use 'ptr.offset' because for
            // vectors with 0-size elements this would return the
            // same pointer.
            self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            let old = self.ptr;
            self.ptr = unsafe { self.ptr.offset(1) };

            Some(unsafe { ptr::read(old) })
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = if mem::size_of::<T>() == 0 {
            (self.end as usize).wrapping_sub(self.ptr as usize)
        } else {
            unsafe { self.end.offset_from(self.ptr) as usize }
        };
        (exact, Some(exact))
    }

    #[inline]
    fn count(self) -> usize {
        self.len()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
    #[inline]
    fn next_back(&mut self) -> Option<T> {
        if self.end == self.ptr {
            None
        } else if mem::size_of::<T>() == 0 {
            // See above for why 'ptr.offset' isn't used
            self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            self.end = unsafe { self.end.offset(-1) };

            Some(unsafe { ptr::read(self.end) })
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
    fn is_empty(&self) -> bool {
        self.ptr == self.end
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
    #[cfg(not(test))]
    fn clone(&self) -> Self {
        self.as_slice().to_vec_in(self.alloc.clone()).into_iter()
    }
    #[cfg(test)]
    fn clone(&self) -> Self {
        crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> {
    fn drop(&mut self) {
        struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter<T, A>);

        impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
            fn drop(&mut self) {
                unsafe {
                    // `IntoIter::alloc` is not used anymore after this
                    let alloc = ptr::read(&self.0.alloc);
                    // RawVec handles deallocation
                    let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
                }
            }
        }

        let guard = DropGuard(self);
        // destroy the remaining elements
        unsafe {
            ptr::drop_in_place(guard.0.as_raw_mut_slice());
        }
        // now `guard` will be dropped and do the rest
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> InPlaceIterable for IntoIter<T, A> {}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> SourceIter for IntoIter<T, A> {
    type Source = Self;

    #[inline]
    unsafe fn as_inner(&mut self) -> &mut Self::Source {
        self
    }
}

// internal helper trait for in-place iteration specialization.
#[rustc_specialization_trait]
pub(crate) trait AsIntoIter {
    type Item;
    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item>;
}

impl<T> AsIntoIter for IntoIter<T> {
    type Item = T;

    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item> {
        self
    }
}
<commit_msg>Add back TrustedRandomAccess-specialization for Vec, but only without coercions<commit_after>use crate::alloc::{Allocator, Global};
use crate::raw_vec::RawVec;
use core::fmt;
use core::intrinsics::arith_offset;
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce};
use core::marker::PhantomData;
use core::mem::{self};
use core::ptr::{self, NonNull};
use core::slice::{self};

/// An iterator that moves out of a vector.
///
/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec)
/// (provided by the [`IntoIterator`] trait).
///
/// # Example
///
/// ```
/// let v = vec![0, 1, 2];
/// let iter: std::vec::IntoIter<_> = v.into_iter();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<
    T,
    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
    pub(super) buf: NonNull<T>,
    pub(super) phantom: PhantomData<T>,
    pub(super) cap: usize,
    pub(super) alloc: A,
    pub(super) ptr: *const T,
    pub(super) end: *const T,
}

#[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}

impl<T, A: Allocator> IntoIter<T, A> {
    /// Returns the remaining items of this iterator as a slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// let _ = into_iter.next().unwrap();
    /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_slice(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.ptr, self.len()) }
    }

    /// Returns the remaining items of this iterator as a mutable slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// into_iter.as_mut_slice()[2] = 'z';
    /// assert_eq!(into_iter.next().unwrap(), 'a');
    /// assert_eq!(into_iter.next().unwrap(), 'b');
    /// assert_eq!(into_iter.next().unwrap(), 'z');
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        unsafe { &mut *self.as_raw_mut_slice() }
    }

    /// Returns a reference to the underlying allocator.
    #[unstable(feature = "allocator_api", issue = "32838")]
    #[inline]
    pub fn allocator(&self) -> &A {
        &self.alloc
    }

    fn as_raw_mut_slice(&mut self) -> *mut [T] {
        ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
    }

    /// Drops remaining elements and relinquishes the backing allocation.
    ///
    /// This is roughly equivalent to the following, but more efficient
    ///
    /// ```
    /// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter();
    /// (&mut into_iter).for_each(core::mem::drop);
    /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); }
    /// ```
    #[cfg(not(no_global_oom_handling))]
    pub(super) fn forget_allocation_drop_remaining(&mut self) {
        let remaining = self.as_raw_mut_slice();

        // overwrite the individual fields instead of creating a new
        // struct and then overwriting &mut self.
        // this creates less assembly
        self.cap = 0;
        self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
        self.ptr = self.buf.as_ptr();
        self.end = self.buf.as_ptr();

        unsafe {
            ptr::drop_in_place(remaining);
        }
    }
}

#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
impl<T, A: Allocator> AsRef<[T]> for IntoIter<T, A> {
    fn as_ref(&self) -> &[T] {
        self.as_slice()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Sync, A: Allocator> Sync for IntoIter<T, A> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.ptr as *const _ == self.end {
            None
        } else if mem::size_of::<T>() == 0 {
            // purposefully don't use 'ptr.offset' because for
            // vectors with 0-size elements this would return the
            // same pointer.
            self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            let old = self.ptr;
            self.ptr = unsafe { self.ptr.offset(1) };

            Some(unsafe { ptr::read(old) })
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = if mem::size_of::<T>() == 0 {
            (self.end as usize).wrapping_sub(self.ptr as usize)
        } else {
            unsafe { self.end.offset_from(self.ptr) as usize }
        };
        (exact, Some(exact))
    }

    #[inline]
    fn count(self) -> usize {
        self.len()
    }

    #[doc(hidden)]
    unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item
    where
        Self: TrustedRandomAccessNoCoerce,
    {
        // SAFETY: the caller must guarantee that `i` is in bounds of the
        // `Vec<T>`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)`
        // is guaranteed to pointer to an element of the `Vec<T>` and
        // thus guaranteed to be valid to dereference.
        //
        // Also note the implementation of `Self: TrustedRandomAccess` requires
        // that `T: Copy` so reading elements from the buffer doesn't invalidate
        // them for `Drop`.
        unsafe {
            if mem::size_of::<T>() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) }
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
    #[inline]
    fn next_back(&mut self) -> Option<T> {
        if self.end == self.ptr {
            None
        } else if mem::size_of::<T>() == 0 {
            // See above for why 'ptr.offset' isn't used
            self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            self.end = unsafe { self.end.offset(-1) };

            Some(unsafe { ptr::read(self.end) })
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
    fn is_empty(&self) -> bool {
        self.ptr == self.end
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}

#[doc(hidden)]
#[unstable(issue = "none", feature = "std_internals")]
// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr
// and thus we can't implement drop-handling
//
// TrustedRandomAccess (without NoCoerce) must not be implemented because
// subtypes/supertypes of `T` might not be `Copy`
unsafe impl<T, A: Allocator> TrustedRandomAccessNoCoerce for IntoIter<T, A>
where
    T: Copy,
{
    const MAY_HAVE_SIDE_EFFECT: bool = false;
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
    #[cfg(not(test))]
    fn clone(&self) -> Self {
        self.as_slice().to_vec_in(self.alloc.clone()).into_iter()
    }
    #[cfg(test)]
    fn clone(&self) -> Self {
        crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> {
    fn drop(&mut self) {
        struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter<T, A>);

        impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
            fn drop(&mut self) {
                unsafe {
                    // `IntoIter::alloc` is not used anymore after this
                    let alloc = ptr::read(&self.0.alloc);
                    // RawVec handles deallocation
                    let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
                }
            }
        }

        let guard = DropGuard(self);
        // destroy the remaining elements
        unsafe {
            ptr::drop_in_place(guard.0.as_raw_mut_slice());
        }
        // now `guard` will be dropped and do the rest
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> InPlaceIterable for IntoIter<T, A> {}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> SourceIter for IntoIter<T, A> {
    type Source = Self;

    #[inline]
    unsafe fn as_inner(&mut self) -> &mut Self::Source {
        self
    }
}

// internal helper trait for in-place iteration specialization.
#[rustc_specialization_trait]
pub(crate) trait AsIntoIter {
    type Item;
    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item>;
}

impl<T> AsIntoIter for IntoIter<T> {
    type Item = T;

    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item> {
        self
    }
}
<|endoftext|>


<commit_before>//! Compiles the profiler part of the `compiler-rt` library.
//!
//! See the build.rs for libcompiler_builtins crate for details.

use std::env;
use std::path::Path;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    let cfg = &mut cc::Build::new();

    // FIXME: `rerun-if-changed` directives are not currently emitted and the build script
    // will not rerun on changes in these source files or headers included into them.
    let mut profile_sources = vec![
        "GCDAProfiling.c",
        "InstrProfiling.c",
        "InstrProfilingBuffer.c",
        "InstrProfilingFile.c",
        "InstrProfilingMerge.c",
        "InstrProfilingMergeFile.c",
        "InstrProfilingNameVar.c",
        "InstrProfilingPlatformDarwin.c",
        "InstrProfilingPlatformLinux.c",
        "InstrProfilingPlatformOther.c",
        "InstrProfilingPlatformWindows.c",
        "InstrProfilingUtil.c",
        "InstrProfilingValue.c",
        "InstrProfilingWriter.c",
        // This file was renamed in LLVM 10.
        "InstrProfilingRuntime.cc",
        "InstrProfilingRuntime.cpp",
        // These files were added in LLVM 11.
        "InstrProfilingInternal.c",
        "InstrProfilingBiasVar.c",
    ];

    if target.contains("msvc") {
        // Don't pull in extra libraries on MSVC
        cfg.flag("/Zl");
        profile_sources.push("WindowsMMap.c");
        cfg.define("strdup", Some("_strdup"));
        cfg.define("open", Some("_open"));
        cfg.define("fdopen", Some("_fdopen"));
        cfg.define("getpid", Some("_getpid"));
        cfg.define("fileno", Some("_fileno"));
    } else {
        // Turn off various features of gcc and such, mostly copying
        // compiler-rt's build system already
        cfg.flag("-fno-builtin");
        cfg.flag("-fvisibility=hidden");
        cfg.flag("-fomit-frame-pointer");
        cfg.define("VISIBILITY_HIDDEN", None);
        if !target.contains("windows") {
            cfg.define("COMPILER_RT_HAS_UNAME", Some("1"));
        } else {
            profile_sources.push("WindowsMMap.c");
        }
    }

    // Assume that the Unixes we are building this for have fnctl() available
    if env::var_os("CARGO_CFG_UNIX").is_some() {
        cfg.define("COMPILER_RT_HAS_FCNTL_LCK", Some("1"));
    }

    // This should be a pretty good heuristic for when to set
    // COMPILER_RT_HAS_ATOMICS
    if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC")
        .map(|features| features.to_string_lossy().to_lowercase().contains("cas"))
        .unwrap_or(false)
    {
        cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1"));
    }

    // Note that this should exist if we're going to run (otherwise we just
    // don't build profiler builtins at all).
    let root = Path::new("../../src/llvm-project/compiler-rt");

    let src_root = root.join("lib").join("profile");
    for src in profile_sources {
        let path = src_root.join(src);
        if path.exists() {
            cfg.file(path);
        }
    }

    cfg.include(root.join("include"));
    cfg.warnings(false);
    cfg.compile("profiler-rt");
}
<commit_msg>Profiler: reenable atomics after #65214<commit_after>//! Compiles the profiler part of the `compiler-rt` library.
//!
//! See the build.rs for libcompiler_builtins crate for details.

use std::env;
use std::path::Path;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    let cfg = &mut cc::Build::new();

    // FIXME: `rerun-if-changed` directives are not currently emitted and the build script
    // will not rerun on changes in these source files or headers included into them.
    let mut profile_sources = vec![
        "GCDAProfiling.c",
        "InstrProfiling.c",
        "InstrProfilingBuffer.c",
        "InstrProfilingFile.c",
        "InstrProfilingMerge.c",
        "InstrProfilingMergeFile.c",
        "InstrProfilingNameVar.c",
        "InstrProfilingPlatformDarwin.c",
        "InstrProfilingPlatformLinux.c",
        "InstrProfilingPlatformOther.c",
        "InstrProfilingPlatformWindows.c",
        "InstrProfilingUtil.c",
        "InstrProfilingValue.c",
        "InstrProfilingWriter.c",
        // This file was renamed in LLVM 10.
        "InstrProfilingRuntime.cc",
        "InstrProfilingRuntime.cpp",
        // These files were added in LLVM 11.
        "InstrProfilingInternal.c",
        "InstrProfilingBiasVar.c",
    ];

    if target.contains("msvc") {
        // Don't pull in extra libraries on MSVC
        cfg.flag("/Zl");
        profile_sources.push("WindowsMMap.c");
        cfg.define("strdup", Some("_strdup"));
        cfg.define("open", Some("_open"));
        cfg.define("fdopen", Some("_fdopen"));
        cfg.define("getpid", Some("_getpid"));
        cfg.define("fileno", Some("_fileno"));
    } else {
        // Turn off various features of gcc and such, mostly copying
        // compiler-rt's build system already
        cfg.flag("-fno-builtin");
        cfg.flag("-fvisibility=hidden");
        cfg.flag("-fomit-frame-pointer");
        cfg.define("VISIBILITY_HIDDEN", None);
        if !target.contains("windows") {
            cfg.define("COMPILER_RT_HAS_UNAME", Some("1"));
        } else {
            profile_sources.push("WindowsMMap.c");
        }
    }

    // Assume that the Unixes we are building this for have fnctl() available
    if env::var_os("CARGO_CFG_UNIX").is_some() {
        cfg.define("COMPILER_RT_HAS_FCNTL_LCK", Some("1"));
    }

    // This should be a pretty good heuristic for when to set
    // COMPILER_RT_HAS_ATOMICS
    if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC")
        .map(|features| features.to_string_lossy().to_lowercase().contains("ptr"))
        .unwrap_or(false)
    {
        cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1"));
    }

    // Note that this should exist if we're going to run (otherwise we just
    // don't build profiler builtins at all).
    let root = Path::new("../../src/llvm-project/compiler-rt");

    let src_root = root.join("lib").join("profile");
    for src in profile_sources {
        let path = src_root.join(src);
        if path.exists() {
            cfg.file(path);
        }
    }

    cfg.include(root.join("include"));
    cfg.warnings(false);
    cfg.compile("profiler-rt");
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::prelude::*;

use rustc::middle::allocator::AllocatorKind;
use rustc_allocator::{AllocatorTy, ALLOCATOR_METHODS};

pub fn codegen(module: &mut Module<impl Backend + 'static>, kind: AllocatorKind) {
    let usize_ty = module.target_config().pointer_type();

    for method in ALLOCATOR_METHODS {
        let mut arg_tys = Vec::with_capacity(method.inputs.len());
        for ty in method.inputs.iter() {
            match *ty {
                AllocatorTy::Layout => {
                    arg_tys.push(usize_ty); // size
                    arg_tys.push(usize_ty); // align
                }
                AllocatorTy::Ptr => arg_tys.push(usize_ty),
                AllocatorTy::Usize => arg_tys.push(usize_ty),

                AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
            }
        }
        let output = match method.output {
            AllocatorTy::ResultPtr => Some(usize_ty),
            AllocatorTy::Unit => None,

            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
                panic!("invalid allocator output")
            }
        };

        let sig = Signature {
            call_conv: CallConv::Fast,
            params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
            returns: output.into_iter().map(AbiParam::new).collect(),
        };

        let func_id = module
            .declare_function(&format!("__rust_{}", method.name), Linkage::Export, &sig)
            .unwrap();

        let callee_func_id = module
            .declare_function(&kind.fn_name(method.name), Linkage::Import, &sig)
            .unwrap();

        let mut ctx = Context::new();
        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone());
        {
            let mut func_ctx = FunctionBuilderContext::new();
            let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

            let ebb = bcx.create_ebb();
            bcx.switch_to_block(ebb);
            let args = arg_tys
                .into_iter()
                .map(|ty| bcx.append_ebb_param(ebb, ty))
                .collect::<Vec<Value>>();

            let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);

            let call_inst = bcx.ins().call(callee_func_ref, &args);

            let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error
            bcx.ins().return_(&results);
            bcx.seal_all_blocks();
            bcx.finalize();
        }
        module.define_function(func_id, &mut ctx).unwrap();
    }
}
<commit_msg>Fix allocator shim abi<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::prelude::*;

use rustc::middle::allocator::AllocatorKind;
use rustc_allocator::{AllocatorTy, ALLOCATOR_METHODS};

pub fn codegen(module: &mut Module<impl Backend + 'static>, kind: AllocatorKind) {
    let usize_ty = module.target_config().pointer_type();

    for method in ALLOCATOR_METHODS {
        let mut arg_tys = Vec::with_capacity(method.inputs.len());
        for ty in method.inputs.iter() {
            match *ty {
                AllocatorTy::Layout => {
                    arg_tys.push(usize_ty); // size
                    arg_tys.push(usize_ty); // align
                }
                AllocatorTy::Ptr => arg_tys.push(usize_ty),
                AllocatorTy::Usize => arg_tys.push(usize_ty),

                AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
            }
        }
        let output = match method.output {
            AllocatorTy::ResultPtr => Some(usize_ty),
            AllocatorTy::Unit => None,

            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
                panic!("invalid allocator output")
            }
        };

        let mut sig = Signature {
            call_conv: CallConv::Fast,
            params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
            returns: output.into_iter().map(AbiParam::new).collect(),
        };

        let caller_name = format!("__rust_{}", method.name);
        let callee_name = kind.fn_name(method.name);
        //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns);

        sig.call_conv = CallConv::Fast; // "rust" abi
        let func_id = module
            .declare_function(&caller_name, Linkage::Export, &sig)
            .unwrap();

        sig.call_conv = CallConv::SystemV; // "C" abi
        let callee_func_id = module
            .declare_function(&callee_name, Linkage::Import, &sig)
            .unwrap();

        let mut ctx = Context::new();
        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone());
        {
            let mut func_ctx = FunctionBuilderContext::new();
            let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

            let ebb = bcx.create_ebb();
            bcx.switch_to_block(ebb);
            let args = arg_tys
                .into_iter()
                .map(|ty| bcx.append_ebb_param(ebb, ty))
                .collect::<Vec<Value>>();

            let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);

            let call_inst = bcx.ins().call(callee_func_ref, &args);

            let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error
            bcx.ins().return_(&results);
            bcx.seal_all_blocks();
            bcx.finalize();
        }
        module.define_function(func_id, &mut ctx).unwrap();
    }
}
<|endoftext|>


<commit_before>//! This module integrates the buddy heap allocator into the Rust runtime.
use spin::Mutex;

use ::Allocator;
use super::{BuddyHeapAllocator, FreeList};

static ALLOC: Mutex<Option<BuddyHeapAllocator<'static>>>
    = Mutex::new(None);

pub unsafe fn init_heap( start_addr: *mut u8
                       , free_lists: &'static mut [FreeList]
                       , heap_size: usize ) {
    trace!("init_heap() was called.");
    *(ALLOC.lock())
        = Some(BuddyHeapAllocator::new(start_addr, free_lists, heap_size));
}

#[no_mangle]
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
    trace!("__rust_allocate() was called.");
    unsafe {
        ALLOC.lock().as_mut()
             .expect("Cannot allocate memory, no system allocator exists!")
             .allocate(size, align)
             .map(|blck| {
                 trace!("__rust_allocate: allocatedd {:?}", blck);
                 blck })
             .expect("Memory could not be allocated; either the allocator is\
                      out of memory, or the allocation request was invalid.")
    }
}

#[no_mangle]
pub extern "C" fn __rust_deallocate( ptr: *mut u8, old_size: usize
                                   , align: usize ) {
    unsafe {
        ALLOC.lock().as_mut()
             .expect("Cannot deallocate memory, no system allocator exists!")
             .deallocate(ptr, old_size, align)
    }
}

#[no_mangle]
pub extern "C" fn __rust_reallocate( ptr: *mut u8, old_size: usize
                                   , size: usize, align: usize )
                                   -> *mut u8 {
    unsafe {
        ALLOC.lock().as_mut()
             .expect("Cannot reallocate memory, no system allocator exists!")
             .reallocate(ptr, old_size, size, align)
             .expect("Memory could not be reallocated; either the allocator\
                     is out of memory, or the allocation request was invalid.")
     }
}

/// This is currently unsupported, so we just silently ignore it
/// and return the old size.
#[no_mangle]
pub extern "C" fn __rust_reallocate_inplace( ptr: *mut u8, old_size: usize
                                           , _size: usize, _align: usize )
                                           -> usize {
    old_size
}

#[no_mangle]
pub extern "C" fn __rust_usable_size(size: usize, _align: usize) -> usize {
    size
}
<commit_msg>[alloc] Allocator system integration behaves reasonably now. (It returns null pointers rather than panicking.)<commit_after>//! This module integrates the buddy heap allocator into the Rust runtime.
use spin::Mutex;
use core::ptr;

use ::Allocator;
use super::{BuddyHeapAllocator, FreeList};

static ALLOC: Mutex<Option<BuddyHeapAllocator<'static>>>
    = Mutex::new(None);

pub unsafe fn init_heap( start_addr: *mut u8
                       , free_lists: &'static mut [FreeList]
                       , heap_size: usize ) {
    trace!("init_heap() was called.");
    *(ALLOC.lock())
        = Some(BuddyHeapAllocator::new(start_addr, free_lists, heap_size));
}

#[no_mangle]
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
    trace!("__rust_allocate() was called.");
    unsafe {
        ALLOC.lock().as_mut()
             .expect("Cannot allocate memory, no system allocator exists!")
             .allocate(size, align)
             .map(|blck| {
                 trace!("__rust_allocate: allocatedd {:?}", blck);
                 blck })
             .unwrap_or(ptr::null_mut())
            //  .expect("Memory could not be allocated; either the allocator is\
            //           out of memory, or the allocation request was invalid.")
    }
}

#[no_mangle]
pub extern "C" fn __rust_deallocate( ptr: *mut u8, old_size: usize
                                   , align: usize ) {
    unsafe {
        ALLOC.lock().as_mut()
             .expect("Cannot deallocate memory, no system allocator exists!")
             .deallocate(ptr, old_size, align)
    }
}

#[no_mangle]
pub extern "C" fn __rust_reallocate( ptr: *mut u8, old_size: usize
                                   , size: usize, align: usize )
                                   -> *mut u8 {
    unsafe {
        ALLOC.lock().as_mut()
             .expect("Cannot reallocate memory, no system allocator exists!")
             .reallocate(ptr, old_size, size, align)
             .unwrap_or(ptr::null_mut())
            //  .expect("Memory could not be reallocated; either the allocator\
            //          is out of memory, or the allocation request was invalid.")
     }
}

/// This is currently unsupported, so we just silently ignore it
/// and return the old size.
#[no_mangle]
pub extern "C" fn __rust_reallocate_inplace( ptr: *mut u8, old_size: usize
                                           , _size: usize, _align: usize )
                                           -> usize {
    old_size
}

#[no_mangle]
pub extern "C" fn __rust_usable_size(size: usize, _align: usize) -> usize {
    size
}
<|endoftext|>