<commit_before>use memchr::{memchr, memrchr};
use regex::bytes::{Regex, RegexBuilder};
use syntax;

use literals::LiteralSets;
use nonl;
use Result;

/// A matched line.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Match {
    start: usize,
    end: usize,
}

impl Match {
    /// Create a new empty match value.
    pub fn new() -> Match {
        Match::default()
    }

    /// Return the starting byte offset of the line that matched.
    #[inline]
    pub fn start(&self) -> usize {
        self.start
    }

    /// Return the ending byte offset of the line that matched.
    #[inline]
    pub fn end(&self) -> usize {
        self.end
    }
}

/// A fast line oriented regex searcher.
#[derive(Clone, Debug)]
pub struct Grep {
    re: Regex,
    required: Option<Regex>,
    opts: Options,
}

/// A builder for a grep searcher.
#[derive(Clone, Debug)]
pub struct GrepBuilder {
    pattern: String,
    opts: Options,
}

#[derive(Clone, Debug)]
struct Options {
    case_insensitive: bool,
    line_terminator: u8,
    size_limit: usize,
    dfa_size_limit: usize,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            case_insensitive: false,
            line_terminator: b'\n',
            size_limit: 10 * (1 << 20),
            dfa_size_limit: 10 * (1 << 20),
        }
    }
}

impl GrepBuilder {
    /// Create a new builder for line searching.
    ///
    /// The pattern given should be a regular expression. The precise syntax
    /// supported is documented on the regex crate.
    pub fn new(pattern: &str) -> GrepBuilder {
        GrepBuilder {
            pattern: pattern.to_string(),
            opts: Options::default(),
        }
    }

    /// Set the line terminator.
    ///
    /// The line terminator can be any ASCII character and serves to delineate
    /// the match boundaries in the text searched.
    ///
    /// This panics if `ascii_byte` is greater than `0x7F` (i.e., not ASCII).
    pub fn line_terminator(mut self, ascii_byte: u8) -> GrepBuilder {
        assert!(ascii_byte <= 0x7F);
        self.opts.line_terminator = ascii_byte;
        self
    }

    /// Set the case sensitive flag (`i`) on the regex.
    pub fn case_insensitive(mut self, yes: bool) -> GrepBuilder {
        self.opts.case_insensitive = yes;
        self
    }

    /// Set the approximate size limit of the compiled regular expression.
    ///
    /// This roughly corresponds to the number of bytes occupied by a
    /// single compiled program. If the program exceeds this number, then a
    /// compilation error is returned.
    pub fn size_limit(mut self, limit: usize) -> GrepBuilder {
        self.opts.size_limit = limit;
        self
    }

    /// Set the approximate size of the cache used by the DFA.
    ///
    /// This roughly corresponds to the number of bytes that the DFA will use
    /// while searching.
    ///
    /// Note that this is a per thread limit. There is no way to set a global
    /// limit. In particular, if a regex is used from multiple threads
    /// simulanteously, then each thread may use up to the number of bytes
    /// specified here.
    pub fn dfa_size_limit(mut self, limit: usize) -> GrepBuilder {
        self.opts.dfa_size_limit = limit;
        self
    }

    /// Create a line searcher.
    ///
    /// If there was a problem parsing or compiling the regex with the given
    /// options, then an error is returned.
    pub fn build(self) -> Result<Grep> {
        let expr = try!(self.parse());
        let literals = LiteralSets::create(&expr);
        let re = try!(
            RegexBuilder::new(&expr.to_string())
                .case_insensitive(self.opts.case_insensitive)
                .multi_line(true)
                .unicode(true)
                .size_limit(self.opts.size_limit)
                .dfa_size_limit(self.opts.dfa_size_limit)
                .compile()
        );
        Ok(Grep {
            re: re,
            required: literals.to_regex(),
            opts: self.opts,
        })
    }

    /// Parses the underlying pattern and ensures the pattern can never match
    /// the line terminator.
    fn parse(&self) -> Result<syntax::Expr> {
        let expr =
            try!(syntax::ExprBuilder::new()
                 .allow_bytes(true)
                 .unicode(true)
                 .case_insensitive(self.opts.case_insensitive)
                 .parse(&self.pattern));
        debug!("regex ast:\n{:#?}", expr);
        Ok(try!(nonl::remove(expr, self.opts.line_terminator)))
    }
}

impl Grep {
    /// Returns a reference to the underlying regex used by the searcher.
    pub fn regex(&self) -> &Regex {
        &self.re
    }

    /// Returns an iterator over all matches in the given buffer.
    pub fn iter<'b, 's>(&'s self, buf: &'b [u8]) -> Iter<'b, 's> {
        Iter {
            searcher: self,
            buf: buf,
            start: 0,
        }
    }

    /// Fills in the next line that matches in the given buffer starting at
    /// the position given.
    ///
    /// If no match could be found, `false` is returned, otherwise, `true` is
    /// returned.
    pub fn read_match(
        &self,
        mat: &mut Match,
        buf: &[u8],
        mut start: usize,
    ) -> bool {
        if start >= buf.len() {
            return false;
        }
        if let Some(ref req) = self.required {
            while start < buf.len() {
                let e = match req.shortest_match(&buf[start..]) {
                    None => return false,
                    Some(e) => start + e,
                };
                let (prevnl, nextnl) = self.find_line(buf, e, e);
                match self.re.shortest_match(&buf[prevnl..nextnl]) {
                    None => {
                        start = nextnl + 1;
                        continue;
                    }
                    Some(_) => {
                        self.fill_match(mat, prevnl, nextnl);
                        return true;
                    }
                }
            }
            false
        } else {
            let e = match self.re.shortest_match(&buf[start..]) {
                None => return false,
                Some(e) => start + e,
            };
            let (s, e) = self.find_line(buf, e, e);
            self.fill_match(mat, s, e);
            true
        }
    }

    fn fill_match(&self, mat: &mut Match, start: usize, end: usize) {
        mat.start = start;
        mat.end = end;
    }

    fn find_line(&self, buf: &[u8], s: usize, e: usize) -> (usize, usize) {
        (self.find_line_start(buf, s), self.find_line_end(buf, e))
    }

    fn find_line_start(&self, buf: &[u8], pos: usize) -> usize {
        memrchr(self.opts.line_terminator, &buf[0..pos]).map_or(0, |i| i + 1)
    }

    fn find_line_end(&self, buf: &[u8], pos: usize) -> usize {
        memchr(self.opts.line_terminator, &buf[pos..])
            .map_or(buf.len(), |i| pos + i + 1)
    }
}

/// An iterator over all matches in a particular buffer.
///
/// `'b` refers to the lifetime of the buffer, and `'s` refers to the lifetime
/// of the searcher.
pub struct Iter<'b, 's> {
    searcher: &'s Grep,
    buf: &'b [u8],
    start: usize,
}

impl<'b, 's> Iterator for Iter<'b, 's> {
    type Item = Match;

    fn next(&mut self) -> Option<Match> {
        let mut mat = Match::default();
        if !self.searcher.read_match(&mut mat, self.buf, self.start) {
            self.start = self.buf.len();
            return None;
        }
        self.start = mat.end;
        Some(mat)
    }
}

#[cfg(test)]
mod tests {
    #![allow(unused_imports)]

    use memchr::{memchr, memrchr};
    use regex::bytes::Regex;

    use super::{GrepBuilder, Match};

    static SHERLOCK: &'static [u8] = include_bytes!("./data/sherlock.txt");

    #[allow(dead_code)]
    fn s(bytes: &[u8]) -> String {
        String::from_utf8(bytes.to_vec()).unwrap()
    }

    fn find_lines(pat: &str, haystack: &[u8]) -> Vec<Match> {
        let re = Regex::new(pat).unwrap();
        let mut lines = vec![];
        for (s, e) in re.find_iter(haystack) {
            let start = memrchr(b'\n', &haystack[..s])
                        .map_or(0, |i| i + 1);
            let end = memchr(b'\n', &haystack[e..])
                      .map_or(haystack.len(), |i| e + i + 1);
            lines.push(Match {
                start: start,
                end: end,
            });
        }
        lines
    }

    fn grep_lines(pat: &str, haystack: &[u8]) -> Vec<Match> {
        let g = GrepBuilder::new(pat).build().unwrap();
        g.iter(haystack).collect()
    }

    #[test]
    fn buffered_literal() {
        let expected = find_lines("Sherlock Holmes", SHERLOCK);
        let got = grep_lines("Sherlock Holmes", SHERLOCK);
        assert_eq!(expected.len(), got.len());
        assert_eq!(expected, got);
    }
}
<commit_msg>Fix off-by-one bug in searcher.<commit_after>use memchr::{memchr, memrchr};
use regex::bytes::{Regex, RegexBuilder};
use syntax;

use literals::LiteralSets;
use nonl;
use Result;

/// A matched line.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Match {
    start: usize,
    end: usize,
}

impl Match {
    /// Create a new empty match value.
    pub fn new() -> Match {
        Match::default()
    }

    /// Return the starting byte offset of the line that matched.
    #[inline]
    pub fn start(&self) -> usize {
        self.start
    }

    /// Return the ending byte offset of the line that matched.
    #[inline]
    pub fn end(&self) -> usize {
        self.end
    }
}

/// A fast line oriented regex searcher.
#[derive(Clone, Debug)]
pub struct Grep {
    re: Regex,
    required: Option<Regex>,
    opts: Options,
}

/// A builder for a grep searcher.
#[derive(Clone, Debug)]
pub struct GrepBuilder {
    pattern: String,
    opts: Options,
}

#[derive(Clone, Debug)]
struct Options {
    case_insensitive: bool,
    line_terminator: u8,
    size_limit: usize,
    dfa_size_limit: usize,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            case_insensitive: false,
            line_terminator: b'\n',
            size_limit: 10 * (1 << 20),
            dfa_size_limit: 10 * (1 << 20),
        }
    }
}

impl GrepBuilder {
    /// Create a new builder for line searching.
    ///
    /// The pattern given should be a regular expression. The precise syntax
    /// supported is documented on the regex crate.
    pub fn new(pattern: &str) -> GrepBuilder {
        GrepBuilder {
            pattern: pattern.to_string(),
            opts: Options::default(),
        }
    }

    /// Set the line terminator.
    ///
    /// The line terminator can be any ASCII character and serves to delineate
    /// the match boundaries in the text searched.
    ///
    /// This panics if `ascii_byte` is greater than `0x7F` (i.e., not ASCII).
    pub fn line_terminator(mut self, ascii_byte: u8) -> GrepBuilder {
        assert!(ascii_byte <= 0x7F);
        self.opts.line_terminator = ascii_byte;
        self
    }

    /// Set the case sensitive flag (`i`) on the regex.
    pub fn case_insensitive(mut self, yes: bool) -> GrepBuilder {
        self.opts.case_insensitive = yes;
        self
    }

    /// Set the approximate size limit of the compiled regular expression.
    ///
    /// This roughly corresponds to the number of bytes occupied by a
    /// single compiled program. If the program exceeds this number, then a
    /// compilation error is returned.
    pub fn size_limit(mut self, limit: usize) -> GrepBuilder {
        self.opts.size_limit = limit;
        self
    }

    /// Set the approximate size of the cache used by the DFA.
    ///
    /// This roughly corresponds to the number of bytes that the DFA will use
    /// while searching.
    ///
    /// Note that this is a per thread limit. There is no way to set a global
    /// limit. In particular, if a regex is used from multiple threads
    /// simulanteously, then each thread may use up to the number of bytes
    /// specified here.
    pub fn dfa_size_limit(mut self, limit: usize) -> GrepBuilder {
        self.opts.dfa_size_limit = limit;
        self
    }

    /// Create a line searcher.
    ///
    /// If there was a problem parsing or compiling the regex with the given
    /// options, then an error is returned.
    pub fn build(self) -> Result<Grep> {
        let expr = try!(self.parse());
        let literals = LiteralSets::create(&expr);
        let re = try!(
            RegexBuilder::new(&expr.to_string())
                .case_insensitive(self.opts.case_insensitive)
                .multi_line(true)
                .unicode(true)
                .size_limit(self.opts.size_limit)
                .dfa_size_limit(self.opts.dfa_size_limit)
                .compile()
        );
        Ok(Grep {
            re: re,
            required: literals.to_regex(),
            opts: self.opts,
        })
    }

    /// Parses the underlying pattern and ensures the pattern can never match
    /// the line terminator.
    fn parse(&self) -> Result<syntax::Expr> {
        let expr =
            try!(syntax::ExprBuilder::new()
                 .allow_bytes(true)
                 .unicode(true)
                 .case_insensitive(self.opts.case_insensitive)
                 .parse(&self.pattern));
        debug!("regex ast:\n{:#?}", expr);
        Ok(try!(nonl::remove(expr, self.opts.line_terminator)))
    }
}

impl Grep {
    /// Returns a reference to the underlying regex used by the searcher.
    pub fn regex(&self) -> &Regex {
        &self.re
    }

    /// Returns an iterator over all matches in the given buffer.
    pub fn iter<'b, 's>(&'s self, buf: &'b [u8]) -> Iter<'b, 's> {
        Iter {
            searcher: self,
            buf: buf,
            start: 0,
        }
    }

    /// Fills in the next line that matches in the given buffer starting at
    /// the position given.
    ///
    /// If no match could be found, `false` is returned, otherwise, `true` is
    /// returned.
    pub fn read_match(
        &self,
        mat: &mut Match,
        buf: &[u8],
        mut start: usize,
    ) -> bool {
        if start >= buf.len() {
            return false;
        }
        if let Some(ref req) = self.required {
            while start < buf.len() {
                let e = match req.shortest_match(&buf[start..]) {
                    None => return false,
                    Some(e) => start + e,
                };
                let (prevnl, nextnl) = self.find_line(buf, e, e);
                match self.re.shortest_match(&buf[prevnl..nextnl]) {
                    None => {
                        start = nextnl;
                        continue;
                    }
                    Some(_) => {
                        self.fill_match(mat, prevnl, nextnl);
                        return true;
                    }
                }
            }
            false
        } else {
            let e = match self.re.shortest_match(&buf[start..]) {
                None => return false,
                Some(e) => start + e,
            };
            let (s, e) = self.find_line(buf, e, e);
            self.fill_match(mat, s, e);
            true
        }
    }

    fn fill_match(&self, mat: &mut Match, start: usize, end: usize) {
        mat.start = start;
        mat.end = end;
    }

    fn find_line(&self, buf: &[u8], s: usize, e: usize) -> (usize, usize) {
        (self.find_line_start(buf, s), self.find_line_end(buf, e))
    }

    fn find_line_start(&self, buf: &[u8], pos: usize) -> usize {
        memrchr(self.opts.line_terminator, &buf[0..pos]).map_or(0, |i| i + 1)
    }

    fn find_line_end(&self, buf: &[u8], pos: usize) -> usize {
        memchr(self.opts.line_terminator, &buf[pos..])
            .map_or(buf.len(), |i| pos + i + 1)
    }
}

/// An iterator over all matches in a particular buffer.
///
/// `'b` refers to the lifetime of the buffer, and `'s` refers to the lifetime
/// of the searcher.
pub struct Iter<'b, 's> {
    searcher: &'s Grep,
    buf: &'b [u8],
    start: usize,
}

impl<'b, 's> Iterator for Iter<'b, 's> {
    type Item = Match;

    fn next(&mut self) -> Option<Match> {
        let mut mat = Match::default();
        if !self.searcher.read_match(&mut mat, self.buf, self.start) {
            self.start = self.buf.len();
            return None;
        }
        self.start = mat.end;
        Some(mat)
    }
}

#[cfg(test)]
mod tests {
    #![allow(unused_imports)]

    use memchr::{memchr, memrchr};
    use regex::bytes::Regex;

    use super::{GrepBuilder, Match};

    static SHERLOCK: &'static [u8] = include_bytes!("./data/sherlock.txt");

    #[allow(dead_code)]
    fn s(bytes: &[u8]) -> String {
        String::from_utf8(bytes.to_vec()).unwrap()
    }

    fn find_lines(pat: &str, haystack: &[u8]) -> Vec<Match> {
        let re = Regex::new(pat).unwrap();
        let mut lines = vec![];
        for (s, e) in re.find_iter(haystack) {
            let start = memrchr(b'\n', &haystack[..s])
                        .map_or(0, |i| i + 1);
            let end = memchr(b'\n', &haystack[e..])
                      .map_or(haystack.len(), |i| e + i + 1);
            lines.push(Match {
                start: start,
                end: end,
            });
        }
        lines
    }

    fn grep_lines(pat: &str, haystack: &[u8]) -> Vec<Match> {
        let g = GrepBuilder::new(pat).build().unwrap();
        g.iter(haystack).collect()
    }

    #[test]
    fn buffered_literal() {
        let expected = find_lines("Sherlock Holmes", SHERLOCK);
        let got = grep_lines("Sherlock Holmes", SHERLOCK);
        assert_eq!(expected.len(), got.len());
        assert_eq!(expected, got);
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.

use crate::rocks_metrics::*;

use file_system::{get_io_type, set_io_type, IOType};
use rocksdb::{
    CompactionJobInfo, DBBackgroundErrorReason, FlushJobInfo, IngestionInfo, SubcompactionJobInfo,
    WriteStallInfo,
};
use tikv_util::set_panic_mark;

pub struct RocksEventListener {
    db_name: String,
}

impl RocksEventListener {
    pub fn new(db_name: &str) -> RocksEventListener {
        RocksEventListener {
            db_name: db_name.to_owned(),
        }
    }
}

impl rocksdb::EventListener for RocksEventListener {
    fn on_flush_begin(&self, _info: &FlushJobInfo) {
        set_io_type(IOType::Flush);
    }

    fn on_flush_completed(&self, info: &FlushJobInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "flush"])
            .inc();
        if get_io_type() == IOType::Flush {
            set_io_type(IOType::Other);
        }
    }

    fn on_compaction_begin(&self, info: &CompactionJobInfo) {
        if info.base_input_level() == 0 {
            set_io_type(IOType::LevelZeroCompaction);
        } else {
            set_io_type(IOType::Compaction);
        }
    }

    fn on_compaction_completed(&self, info: &CompactionJobInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "compaction"])
            .inc();
        STORE_ENGINE_COMPACTION_DURATIONS_VEC
            .with_label_values(&[&self.db_name, info.cf_name()])
            .observe(info.elapsed_micros() as f64 / 1_000_000.0);
        STORE_ENGINE_COMPACTION_NUM_CORRUPT_KEYS_VEC
            .with_label_values(&[&self.db_name, info.cf_name()])
            .inc_by(info.num_corrupt_keys());
        STORE_ENGINE_COMPACTION_REASON_VEC
            .with_label_values(&[
                &self.db_name,
                info.cf_name(),
                &info.compaction_reason().to_string(),
            ])
            .inc();
        if info.base_input_level() == 0 && get_io_type() == IOType::LevelZeroCompaction
            || info.base_input_level() != 0 && get_io_type() == IOType::Compaction
        {
            set_io_type(IOType::Other);
        }
    }

    fn on_subcompaction_begin(&self, info: &SubcompactionJobInfo) {
        if info.base_input_level() == 0 {
            set_io_type(IOType::LevelZeroCompaction);
        } else {
            set_io_type(IOType::Compaction);
        }
    }

    fn on_subcompaction_completed(&self, info: &SubcompactionJobInfo) {
        if info.base_input_level() == 0 && get_io_type() == IOType::LevelZeroCompaction
            || info.base_input_level() != 0 && get_io_type() == IOType::Compaction
        {
            set_io_type(IOType::Other);
        }
    }

    fn on_external_file_ingested(&self, info: &IngestionInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "ingestion"])
            .inc();
        STORE_ENGINE_INGESTION_PICKED_LEVEL_VEC
            .with_label_values(&[&self.db_name, info.cf_name()])
            .observe(info.picked_level() as f64);
    }

    fn on_background_error(&self, reason: DBBackgroundErrorReason, result: Result<(), String>) {
        assert!(result.is_err());
        if let Err(err) = result {
            let r = match reason {
                DBBackgroundErrorReason::Flush => "flush",
                DBBackgroundErrorReason::Compaction => "compaction",
                DBBackgroundErrorReason::WriteCallback => "write_callback",
                DBBackgroundErrorReason::MemTable => "memtable",
            };
            // Avoid tikv from restarting if rocksdb get corruption.
            if err.starts_with("Corruption") {
                set_panic_mark();
            }
            panic!(
                "rocksdb background error. db: {}, reason: {}, error: {}",
                self.db_name, r, err
            );
        }
    }

    fn on_stall_conditions_changed(&self, info: &WriteStallInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "stall_conditions_changed"])
            .inc();
    }
}
<commit_msg>engine_rocks: ignore NoSpace error during flush or compaction (#11225)<commit_after>// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.

use crate::rocks_metrics::*;

use file_system::{get_io_type, set_io_type, IOType};
use rocksdb::{
    CompactionJobInfo, DBBackgroundErrorReason, FlushJobInfo, IngestionInfo, SubcompactionJobInfo,
    WriteStallInfo,
};
use tikv_util::set_panic_mark;

// Message for RocksDB status subcode kNoSpace.
const NO_SPACE_ERROR: &str = "IO error: No space left on device";

pub struct RocksEventListener {
    db_name: String,
}

impl RocksEventListener {
    pub fn new(db_name: &str) -> RocksEventListener {
        RocksEventListener {
            db_name: db_name.to_owned(),
        }
    }
}

impl rocksdb::EventListener for RocksEventListener {
    fn on_flush_begin(&self, _info: &FlushJobInfo) {
        set_io_type(IOType::Flush);
    }

    fn on_flush_completed(&self, info: &FlushJobInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "flush"])
            .inc();
        if get_io_type() == IOType::Flush {
            set_io_type(IOType::Other);
        }
    }

    fn on_compaction_begin(&self, info: &CompactionJobInfo) {
        if info.base_input_level() == 0 {
            set_io_type(IOType::LevelZeroCompaction);
        } else {
            set_io_type(IOType::Compaction);
        }
    }

    fn on_compaction_completed(&self, info: &CompactionJobInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "compaction"])
            .inc();
        STORE_ENGINE_COMPACTION_DURATIONS_VEC
            .with_label_values(&[&self.db_name, info.cf_name()])
            .observe(info.elapsed_micros() as f64 / 1_000_000.0);
        STORE_ENGINE_COMPACTION_NUM_CORRUPT_KEYS_VEC
            .with_label_values(&[&self.db_name, info.cf_name()])
            .inc_by(info.num_corrupt_keys());
        STORE_ENGINE_COMPACTION_REASON_VEC
            .with_label_values(&[
                &self.db_name,
                info.cf_name(),
                &info.compaction_reason().to_string(),
            ])
            .inc();
        if info.base_input_level() == 0 && get_io_type() == IOType::LevelZeroCompaction
            || info.base_input_level() != 0 && get_io_type() == IOType::Compaction
        {
            set_io_type(IOType::Other);
        }
    }

    fn on_subcompaction_begin(&self, info: &SubcompactionJobInfo) {
        if info.base_input_level() == 0 {
            set_io_type(IOType::LevelZeroCompaction);
        } else {
            set_io_type(IOType::Compaction);
        }
    }

    fn on_subcompaction_completed(&self, info: &SubcompactionJobInfo) {
        if info.base_input_level() == 0 && get_io_type() == IOType::LevelZeroCompaction
            || info.base_input_level() != 0 && get_io_type() == IOType::Compaction
        {
            set_io_type(IOType::Other);
        }
    }

    fn on_external_file_ingested(&self, info: &IngestionInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "ingestion"])
            .inc();
        STORE_ENGINE_INGESTION_PICKED_LEVEL_VEC
            .with_label_values(&[&self.db_name, info.cf_name()])
            .observe(info.picked_level() as f64);
    }

    fn on_background_error(&self, reason: DBBackgroundErrorReason, result: Result<(), String>) {
        assert!(result.is_err());
        if let Err(err) = result {
            if matches!(
                reason,
                DBBackgroundErrorReason::Flush | DBBackgroundErrorReason::Compaction
            ) && err.starts_with(NO_SPACE_ERROR)
            {
                // Ignore NoSpace error and let RocksDB automatically recover.
                return;
            }
            let r = match reason {
                DBBackgroundErrorReason::Flush => "flush",
                DBBackgroundErrorReason::Compaction => "compaction",
                DBBackgroundErrorReason::WriteCallback => "write_callback",
                DBBackgroundErrorReason::MemTable => "memtable",
            };
            // Avoid tikv from restarting if rocksdb get corruption.
            if err.starts_with("Corruption") {
                set_panic_mark();
            }
            panic!(
                "rocksdb background error. db: {}, reason: {}, error: {}",
                self.db_name, r, err
            );
        }
    }

    fn on_stall_conditions_changed(&self, info: &WriteStallInfo) {
        STORE_ENGINE_EVENT_COUNTER_VEC
            .with_label_values(&[&self.db_name, info.cf_name(), "stall_conditions_changed"])
            .inc();
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate clap;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate commercetools;

#[macro_use]
extern crate serde_derive;

extern crate serde_json;

use clap::{App, Arg};
use commercetools::client::CtpClient;
use commercetools::region::Region;
use std::collections::HashMap;
use std::str::FromStr;

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct Reference {
    pub typeId: String,
    pub id: String,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct ProductVariant {
    pub id: u64,
    pub sku: Option<String>,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct ProductData {
    pub name: HashMap<String, String>,
    pub categories: Vec<Reference>,
    pub description: Option<HashMap<String, String>>,
    pub slug: HashMap<String, String>,
    pub metaTitle: Option<HashMap<String, String>>,
    pub metaDescription: Option<HashMap<String, String>>,
    pub metaKeywords: Option<HashMap<String, String>>,
    pub masterVariant: ProductVariant,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct ProductCatalogData {
    pub published: bool,
    pub hasStagedChanges: bool,
    pub current: ProductData,
    pub staged: ProductData,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct Product {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub masterData: ProductCatalogData,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct Review {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub text: Option<String>,
}

fn main() {
    env_logger::init().unwrap();
    let matches = App::new("sphere")
        .version("1.0")
        .author("Yann Simon <yann.simon@commercetools.com>")
        .args_from_usage("<PROJECT_KEY> 'project key' \n\
             <CLIENT_ID> 'client ID' \n\
             <CLIENT_SECRET> 'client secret' \n\
            --region=[Europe|NorthAmerica] 'region to use (default to Europe)'")
        .arg(Arg::with_name("permissions")
            .short("p")
            .long("permission")
            .help("permissions (default to manage_project)")
            .multiple(true)
            .takes_value(true))
        .get_matches();

    let project_key = matches.value_of("PROJECT_KEY").unwrap();
    let client_id = matches.value_of("CLIENT_ID").unwrap();
    let client_secret = matches.value_of("CLIENT_SECRET").unwrap();
    let region =
        matches.value_of("region").map(|s| Region::from_str(s).unwrap()).unwrap_or(Region::Europe);
    let permissions: Vec<&str> = if matches.is_present("permissions") {
        matches.values_of("permissions").unwrap().collect()
    } else {
        vec!["manage_project"]
    };

    let mut ctp_client = CtpClient::new(&region, project_key, client_id, client_secret)
        .with_permissions(&permissions);

    // simple GET call
    let mut products = ctp_client.get("/products?limit=1").unwrap();
    println!("\nProducts: {}", products.body_as_string().unwrap());

    // paged result of products
    let products2 = ctp_client.list::<Product>("products").unwrap();
    println!("\nList of product ids: {:?}",
             products2.results.iter().map(|p| &p.id).collect::<Vec<&String>>());

    println!("\nFirst product: {:?}", &products2.results.first());

    // read reviews
    let mut reviews = ctp_client.get("/reviews?limit=1").unwrap();
    println!("\nReviews: {}", reviews.body_as_string().unwrap());

    let create = permissions.iter().any(|&p| p == "manage_project" || p == "manage_products");
    if create {
        // create and delete a review
        let create_review = r#"
        {
          "text": "my review"
        }
        "#;
        let mut review_call = ctp_client.post("/reviews", create_review).unwrap();
        let review = review_call.body_as::<Review>().unwrap();
        println!("\n[{}] New Review: {:?}", &review_call.status(), review);

        let url = format!("/reviews/{}?version={}", review.id, review.version);
        let mut deleted_review = ctp_client.delete(&url).unwrap();
        println!("\n[{}] Deleted Review: {:?}",
                 &deleted_review.status(),
                 deleted_review.body_as_string().unwrap());
    }

    // read products IDs with a Graph QL query
    let query = r#"
    {
      products {
        results {
          id
        }
      }
    }
    "#;
    let mut graphql = ctp_client.graphql(query).unwrap();
    println!("\nGraphQL: {}", graphql.body_as_string().unwrap());

}
<commit_msg>clippy: unused macro usage<commit_after>extern crate hyper;
extern crate clap;
extern crate log;
extern crate env_logger;
extern crate commercetools;

#[macro_use]
extern crate serde_derive;

extern crate serde_json;

use clap::{App, Arg};
use commercetools::client::CtpClient;
use commercetools::region::Region;
use std::collections::HashMap;
use std::str::FromStr;

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct Reference {
    pub typeId: String,
    pub id: String,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct ProductVariant {
    pub id: u64,
    pub sku: Option<String>,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct ProductData {
    pub name: HashMap<String, String>,
    pub categories: Vec<Reference>,
    pub description: Option<HashMap<String, String>>,
    pub slug: HashMap<String, String>,
    pub metaTitle: Option<HashMap<String, String>>,
    pub metaDescription: Option<HashMap<String, String>>,
    pub metaKeywords: Option<HashMap<String, String>>,
    pub masterVariant: ProductVariant,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct ProductCatalogData {
    pub published: bool,
    pub hasStagedChanges: bool,
    pub current: ProductData,
    pub staged: ProductData,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct Product {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub masterData: ProductCatalogData,
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
pub struct Review {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub text: Option<String>,
}

fn main() {
    env_logger::init().unwrap();
    let matches = App::new("sphere")
        .version("1.0")
        .author("Yann Simon <yann.simon@commercetools.com>")
        .args_from_usage("<PROJECT_KEY> 'project key' \n\
             <CLIENT_ID> 'client ID' \n\
             <CLIENT_SECRET> 'client secret' \n\
            --region=[Europe|NorthAmerica] 'region to use (default to Europe)'")
        .arg(Arg::with_name("permissions")
            .short("p")
            .long("permission")
            .help("permissions (default to manage_project)")
            .multiple(true)
            .takes_value(true))
        .get_matches();

    let project_key = matches.value_of("PROJECT_KEY").unwrap();
    let client_id = matches.value_of("CLIENT_ID").unwrap();
    let client_secret = matches.value_of("CLIENT_SECRET").unwrap();
    let region =
        matches.value_of("region").map(|s| Region::from_str(s).unwrap()).unwrap_or(Region::Europe);
    let permissions: Vec<&str> = if matches.is_present("permissions") {
        matches.values_of("permissions").unwrap().collect()
    } else {
        vec!["manage_project"]
    };

    let mut ctp_client = CtpClient::new(&region, project_key, client_id, client_secret)
        .with_permissions(&permissions);

    // simple GET call
    let mut products = ctp_client.get("/products?limit=1").unwrap();
    println!("\nProducts: {}", products.body_as_string().unwrap());

    // paged result of products
    let products2 = ctp_client.list::<Product>("products").unwrap();
    println!("\nList of product ids: {:?}",
             products2.results.iter().map(|p| &p.id).collect::<Vec<&String>>());

    println!("\nFirst product: {:?}", &products2.results.first());

    // read reviews
    let mut reviews = ctp_client.get("/reviews?limit=1").unwrap();
    println!("\nReviews: {}", reviews.body_as_string().unwrap());

    let create = permissions.iter().any(|&p| p == "manage_project" || p == "manage_products");
    if create {
        // create and delete a review
        let create_review = r#"
        {
          "text": "my review"
        }
        "#;
        let mut review_call = ctp_client.post("/reviews", create_review).unwrap();
        let review = review_call.body_as::<Review>().unwrap();
        println!("\n[{}] New Review: {:?}", &review_call.status(), review);

        let url = format!("/reviews/{}?version={}", review.id, review.version);
        let mut deleted_review = ctp_client.delete(&url).unwrap();
        println!("\n[{}] Deleted Review: {:?}",
                 &deleted_review.status(),
                 deleted_review.body_as_string().unwrap());
    }

    // read products IDs with a Graph QL query
    let query = r#"
    {
      products {
        results {
          id
        }
      }
    }
    "#;
    let mut graphql = ctp_client.graphql(query).unwrap();
    println!("\nGraphQL: {}", graphql.body_as_string().unwrap());

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::cmp::{max, min};
use std::iter;
use std::fmt;
use std::num;
use std::num::Bounded;

pub enum RangeRelation<T> {
    OverlapsBegin(/* overlap */ T),
    OverlapsEnd(/* overlap */ T),
    ContainedBy,
    Contains,
    Coincides,
    EntirelyBefore,
    EntirelyAfter
}

#[deriving(Clone)]
pub struct Range<T> {
    off: T,
    len: T,
}

impl<T: Int + TotalOrd> fmt::Show for Range<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f.buf, "[{} .. {})", self.begin(), self.end())
    }
}

impl<T: Int + TotalOrd> Range<T> {
    #[inline]
    pub fn new(off: T, len: T) -> Range<T> {
        Range {
            off: off,
            len: len,
        }
    }

    #[inline]
    pub fn empty() -> Range<T> {
        Range::new(num::zero(), num::zero())
    }

    #[inline]
    pub fn begin(&self) -> T { self.off  }
    #[inline]
    pub fn length(&self) -> T { self.len }
    #[inline]
    pub fn end(&self) -> T { self.off + self.len }

    #[inline]
    pub fn eachi(&self) -> iter::Range<T> {
        range(self.off, self.off + self.len)
    }

    #[inline]
    pub fn contains(&self, i: T) -> bool {
        i >= self.begin() && i < self.end()
    }

    #[inline]
    pub fn is_valid_for_string(&self, s: &str) -> bool {
        let s_len = s.len();
        match num::cast(s_len) {
            Some(len) => {
                self.begin() < len && self.end() <= len && self.length() <= len
            },
            None => {
                debug!("Range<T>::is_valid_for_string: string length ({}) is longer than the max \
                        value for T ({})", s_len, { let val: T = Bounded::max_value(); val });
                false
            },
        }
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len.is_zero()
    }

    #[inline]
    pub fn shift_by(&mut self, i: int) {
        self.off = num::cast(self.off.to_int().unwrap() + i).unwrap();
    }

    #[inline]
    pub fn extend_by(&mut self, i: int) {
        self.len = num::cast(self.len.to_int().unwrap() + i).unwrap();
    }

    #[inline]
    pub fn extend_to(&mut self, i: T) {
        self.len = i - self.off;
    }

    #[inline]
    pub fn adjust_by(&mut self, off_i: int, len_i: int) {
        self.off = num::cast(self.off.to_int().unwrap() + off_i).unwrap();
        self.len = num::cast(self.len.to_int().unwrap() + len_i).unwrap();
    }

    #[inline]
    pub fn reset(&mut self, off_i: T, len_i: T) {
        self.off = off_i;
        self.len = len_i;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<T>) -> Range<T> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }

    /// Computes the relationship between two ranges (`self` and `other`),
    /// from the point of view of `self`. So, 'EntirelyBefore' means
    /// that the `self` range is entirely before `other` range.
    #[inline]
    pub fn relation_to_range(&self, other: &Range<T>) -> RangeRelation<T> {
        if other.begin() > self.end() {
            return EntirelyBefore;
        }
        if self.begin() > other.end() {
            return EntirelyAfter;
        }
        if self.begin() == other.begin() && self.end() == other.end() {
            return Coincides;
        }
        if self.begin() <= other.begin() && self.end() >= other.end() {
            return Contains;
        }
        if self.begin() >= other.begin() && self.end() <= other.end() {
            return ContainedBy;
        }
        if self.begin() < other.begin() && self.end() < other.end() {
            let overlap = self.end() - other.begin();
            return OverlapsBegin(overlap);
        }
        if self.begin() > other.begin() && self.end() > other.end() {
            let overlap = other.end() - self.begin();
            return OverlapsEnd(overlap);
        }
        fail!("relation_to_range(): didn't classify self={:?}, other={:?}",
              self, other);
    }

    #[inline]
    pub fn repair_after_coalesced_range(&mut self, other: &Range<T>) {
        let relation = self.relation_to_range(other);
        debug!("repair_after_coalesced_range: possibly repairing range {:?}", self);
        debug!("repair_after_coalesced_range: relation of original range and coalesced range({:?}): {:?}",
               other, relation);
        match relation {
            EntirelyBefore => { },
            EntirelyAfter =>  { self.shift_by(-other.length().to_int().unwrap()); },
            Coincides | ContainedBy =>   { self.reset(other.begin(), num::one()); },
            Contains =>      { self.extend_by(-other.length().to_int().unwrap()); },
            OverlapsBegin(overlap) => { self.extend_by(1 - overlap.to_int().unwrap()); },
            OverlapsEnd(overlap) => {
                let len = self.length() - overlap + num::one();
                self.reset(other.begin(), len);
            }
        };
        debug!("repair_after_coalesced_range: new range: ---- {:?}", self);
    }
}
<commit_msg>Use {} instead of {:?} for debug!ing in util::range<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::cmp::{max, min};
use std::iter;
use std::fmt;
use std::num;
use std::num::Bounded;

#[deriving(Show)]
pub enum RangeRelation<T> {
    OverlapsBegin(/* overlap */ T),
    OverlapsEnd(/* overlap */ T),
    ContainedBy,
    Contains,
    Coincides,
    EntirelyBefore,
    EntirelyAfter
}

#[deriving(Clone)]
pub struct Range<T> {
    off: T,
    len: T,
}

impl<T: Int + TotalOrd> fmt::Show for Range<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f.buf, "[{} .. {})", self.begin(), self.end())
    }
}

impl<T: Int + TotalOrd> Range<T> {
    #[inline]
    pub fn new(off: T, len: T) -> Range<T> {
        Range {
            off: off,
            len: len,
        }
    }

    #[inline]
    pub fn empty() -> Range<T> {
        Range::new(num::zero(), num::zero())
    }

    #[inline]
    pub fn begin(&self) -> T { self.off  }
    #[inline]
    pub fn length(&self) -> T { self.len }
    #[inline]
    pub fn end(&self) -> T { self.off + self.len }

    #[inline]
    pub fn eachi(&self) -> iter::Range<T> {
        range(self.off, self.off + self.len)
    }

    #[inline]
    pub fn contains(&self, i: T) -> bool {
        i >= self.begin() && i < self.end()
    }

    #[inline]
    pub fn is_valid_for_string(&self, s: &str) -> bool {
        let s_len = s.len();
        match num::cast(s_len) {
            Some(len) => {
                self.begin() < len && self.end() <= len && self.length() <= len
            },
            None => {
                debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the max \
                        value for T (max={})", s_len, { let val: T = Bounded::max_value(); val });
                false
            },
        }
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len.is_zero()
    }

    #[inline]
    pub fn shift_by(&mut self, i: int) {
        self.off = num::cast(self.off.to_int().unwrap() + i).unwrap();
    }

    #[inline]
    pub fn extend_by(&mut self, i: int) {
        self.len = num::cast(self.len.to_int().unwrap() + i).unwrap();
    }

    #[inline]
    pub fn extend_to(&mut self, i: T) {
        self.len = i - self.off;
    }

    #[inline]
    pub fn adjust_by(&mut self, off_i: int, len_i: int) {
        self.off = num::cast(self.off.to_int().unwrap() + off_i).unwrap();
        self.len = num::cast(self.len.to_int().unwrap() + len_i).unwrap();
    }

    #[inline]
    pub fn reset(&mut self, off_i: T, len_i: T) {
        self.off = off_i;
        self.len = len_i;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<T>) -> Range<T> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }

    /// Computes the relationship between two ranges (`self` and `other`),
    /// from the point of view of `self`. So, 'EntirelyBefore' means
    /// that the `self` range is entirely before `other` range.
    #[inline]
    pub fn relation_to_range(&self, other: &Range<T>) -> RangeRelation<T> {
        if other.begin() > self.end() {
            return EntirelyBefore;
        }
        if self.begin() > other.end() {
            return EntirelyAfter;
        }
        if self.begin() == other.begin() && self.end() == other.end() {
            return Coincides;
        }
        if self.begin() <= other.begin() && self.end() >= other.end() {
            return Contains;
        }
        if self.begin() >= other.begin() && self.end() <= other.end() {
            return ContainedBy;
        }
        if self.begin() < other.begin() && self.end() < other.end() {
            let overlap = self.end() - other.begin();
            return OverlapsBegin(overlap);
        }
        if self.begin() > other.begin() && self.end() > other.end() {
            let overlap = other.end() - self.begin();
            return OverlapsEnd(overlap);
        }
        fail!("relation_to_range(): didn't classify self={}, other={}",
              self, other);
    }

    #[inline]
    pub fn repair_after_coalesced_range(&mut self, other: &Range<T>) {
        let relation = self.relation_to_range(other);
        debug!("repair_after_coalesced_range: possibly repairing range {}", *self);
        debug!("repair_after_coalesced_range: relation of original range and coalesced range {}: {}",
               *other, relation);
        match relation {
            EntirelyBefore => { },
            EntirelyAfter =>  { self.shift_by(-other.length().to_int().unwrap()); },
            Coincides | ContainedBy =>   { self.reset(other.begin(), num::one()); },
            Contains =>      { self.extend_by(-other.length().to_int().unwrap()); },
            OverlapsBegin(overlap) => { self.extend_by(1 - overlap.to_int().unwrap()); },
            OverlapsEnd(overlap) => {
                let len = self.length() - overlap + num::one();
                self.reset(other.begin(), len);
            }
        };
        debug!("repair_after_coalesced_range: new range: ---- {}", *self);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#[macro_use] extern crate procedural_masquerade;
extern crate phf_codegen;
extern crate proc_macro;
#[macro_use] extern crate quote;
extern crate syn;

use std::ascii::AsciiExt;

define_proc_macros! {
    /// Input: the arms of a `match` expression.
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
    ///
    /// Panic if the arms contain non-string patterns,
    /// or string patterns that contains ASCII uppercase letters.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: &str) -> String {
        let expr = syn::parse_expr(&format!("match x {{ {} }}", input)).unwrap();
        let arms = match expr {
            syn::Expr { node: syn::ExprKind::Match(_, ref arms), .. } => arms,
            _ => panic!("expected a match expression, got {:?}", expr)
        };
        max_len(arms.iter().flat_map(|arm| &arm.pats).filter_map(|pattern| {
            let expr = match *pattern {
                syn::Pat::Lit(ref expr) => expr,
                syn::Pat::Wild |
                syn::Pat::Ident(_, _, None) => return None,
                syn::Pat::Ident(_, _, Some(ref sub_pattern)) => {
                    match **sub_pattern {
                        syn::Pat::Lit(ref expr) => expr,
                        syn::Pat::Wild => return None,
                        _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
                    }
                }
                _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
            };
            match **expr {
                syn::Expr { node: syn::ExprKind::Lit(syn::Lit::Str(ref string, _)), .. } => {
                    assert_eq!(*string, string.to_ascii_lowercase(),
                               "string patterns must be given in ASCII lowercase");
                    Some(string.len())
                }
                _ => panic!("expected string pattern, got {:?}", expr)
            }
        }))
    }

    /// Input: string literals with no separator
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__max_len(input: &str) -> String {
        max_len(syn::parse_token_trees(input).unwrap().iter().map(|tt| string_literal(tt).len()))
    }

    /// Input: parsed as token trees. The first TT is a type. (Can be wrapped in parens.)
    /// following TTs are grouped in pairs, each pair being a key as a string literal
    /// and the corresponding value as a const expression.
    ///
    /// Output: a rust-phf map, with keys ASCII-lowercased:
    /// ```
    /// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
    /// ```
    #[allow(non_snake_case)]
    pub fn cssparser_internal__phf_map(input: &str) -> String {
        let token_trees = syn::parse_token_trees(input).unwrap();
        let value_type = &token_trees[0];
        let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
            let key = string_literal(&chunk[0]);
            let value = &chunk[1];
            (key.to_ascii_lowercase(), quote!(#value).to_string())
        }).collect();

        let mut map = phf_codegen::Map::new();
        map.phf_path("::cssparser::phf");
        for &(ref key, ref value) in &pairs {
            map.entry(&**key, &**value);
        }

        let mut tokens = quote! {
            static MAP: ::cssparser::phf::Map<&'static str, #value_type> =
        };
        let mut initializer_bytes = Vec::new();
        map.build(&mut initializer_bytes).unwrap();
        tokens.append(::std::str::from_utf8(&initializer_bytes).unwrap());
        tokens.append(";");
        tokens.to_string()
    }
}

fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
    let max_length = lengths.max().expect("expected at least one string");
    quote!( const MAX_LENGTH: usize = #max_length; ).to_string()
}

fn string_literal(token: &syn::TokenTree) -> &str {
    match *token {
        syn::TokenTree::Token(syn::Token::Literal(syn::Lit::Str(ref string, _))) => string,
        _ => panic!("expected string literal, got {:?}", token)
    }
}
<commit_msg>Use Tokens::into_string<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#[macro_use] extern crate procedural_masquerade;
extern crate phf_codegen;
extern crate proc_macro;
#[macro_use] extern crate quote;
extern crate syn;

use std::ascii::AsciiExt;

define_proc_macros! {
    /// Input: the arms of a `match` expression.
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
    ///
    /// Panic if the arms contain non-string patterns,
    /// or string patterns that contains ASCII uppercase letters.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: &str) -> String {
        let expr = syn::parse_expr(&format!("match x {{ {} }}", input)).unwrap();
        let arms = match expr {
            syn::Expr { node: syn::ExprKind::Match(_, ref arms), .. } => arms,
            _ => panic!("expected a match expression, got {:?}", expr)
        };
        max_len(arms.iter().flat_map(|arm| &arm.pats).filter_map(|pattern| {
            let expr = match *pattern {
                syn::Pat::Lit(ref expr) => expr,
                syn::Pat::Wild |
                syn::Pat::Ident(_, _, None) => return None,
                syn::Pat::Ident(_, _, Some(ref sub_pattern)) => {
                    match **sub_pattern {
                        syn::Pat::Lit(ref expr) => expr,
                        syn::Pat::Wild => return None,
                        _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
                    }
                }
                _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
            };
            match **expr {
                syn::Expr { node: syn::ExprKind::Lit(syn::Lit::Str(ref string, _)), .. } => {
                    assert_eq!(*string, string.to_ascii_lowercase(),
                               "string patterns must be given in ASCII lowercase");
                    Some(string.len())
                }
                _ => panic!("expected string pattern, got {:?}", expr)
            }
        }))
    }

    /// Input: string literals with no separator
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__max_len(input: &str) -> String {
        max_len(syn::parse_token_trees(input).unwrap().iter().map(|tt| string_literal(tt).len()))
    }

    /// Input: parsed as token trees. The first TT is a type. (Can be wrapped in parens.)
    /// following TTs are grouped in pairs, each pair being a key as a string literal
    /// and the corresponding value as a const expression.
    ///
    /// Output: a rust-phf map, with keys ASCII-lowercased:
    /// ```
    /// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
    /// ```
    #[allow(non_snake_case)]
    pub fn cssparser_internal__phf_map(input: &str) -> String {
        let token_trees = syn::parse_token_trees(input).unwrap();
        let value_type = &token_trees[0];
        let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
            let key = string_literal(&chunk[0]);
            let value = &chunk[1];
            (key.to_ascii_lowercase(), quote!(#value).to_string())
        }).collect();

        let mut map = phf_codegen::Map::new();
        map.phf_path("::cssparser::phf");
        for &(ref key, ref value) in &pairs {
            map.entry(&**key, &**value);
        }

        let mut tokens = quote! {
            static MAP: ::cssparser::phf::Map<&'static str, #value_type> =
        };
        let mut initializer_bytes = Vec::new();
        map.build(&mut initializer_bytes).unwrap();
        tokens.append(::std::str::from_utf8(&initializer_bytes).unwrap());
        tokens.append(";");
        tokens.into_string()
    }
}

fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
    let max_length = lengths.max().expect("expected at least one string");
    quote!( const MAX_LENGTH: usize = #max_length; ).into_string()
}

fn string_literal(token: &syn::TokenTree) -> &str {
    match *token {
        syn::TokenTree::Token(syn::Token::Literal(syn::Lit::Str(ref string, _))) => string,
        _ => panic!("expected string literal, got {:?}", token)
    }
}
<|endoftext|>


<commit_before>use libc::c_int;
use std::ops::Deref;
use tensorflow_sys as tf;

use crate::{AnyTensor, DataType, Result, Shape, Tensor, TensorInner, TensorType};

/// A read-only tensor.
///
/// This ReadonlyTensor is a wrapper around a `Tensor` that is read-only.
/// Some operations that mutate the underlying Tensor are not supported.
#[derive(Debug, Clone, Eq)]
pub struct ReadonlyTensor<T: TensorType> {
    pub(super) inner: T::InnerType,
    pub(super) dims: Vec<u64>,
}

impl<T: TensorType> AnyTensor for ReadonlyTensor<T> {
    fn inner(&self) -> Result<*mut tf::TF_Tensor> {
        self.inner.as_mut_ptr(&self.dims)
    }

    fn data_type(&self) -> DataType {
        T::data_type()
    }
}

impl<T: TensorType> Deref for ReadonlyTensor<T> {
    type Target = [T];

    #[inline]
    fn deref(&self) -> &[T] {
        self.inner.deref()
    }
}

impl<T: TensorType + PartialEq> PartialEq for ReadonlyTensor<T> {
    fn eq(&self, other: &Self) -> bool {
        self.dims == other.dims && self.deref() == other.deref()
    }
}

impl<T: TensorType + PartialEq> PartialEq<Tensor<T>> for ReadonlyTensor<T> {
    fn eq(&self, other: &Tensor<T>) -> bool {
        self.dims == other.dims && self.deref() == other.deref()
    }
}

impl<T: TensorType> ReadonlyTensor<T> {
    /// Get one single value from the Tensor.
    ///
    /// ```
    /// # use tensorflow::Tensor;
    /// # use tensorflow::eager::ReadonlyTensor;
    /// let mut a = Tensor::<i32>::new(&[2, 3, 5]);
    ///
    /// a[1*15 + 1*5 + 1] = 5;
    /// let a = a.freeze();
    /// assert_eq!(a.get(&[1, 1, 1]), 5);
    /// ```
    pub fn get(&self, indices: &[u64]) -> T {
        let index = self.get_index(indices);
        self[index].clone()
    }

    /// Get the array index from rows / columns indices.
    ///
    /// ```
    /// # use tensorflow::Tensor;
    /// # use tensorflow::eager::ReadonlyTensor;
    /// let a = Tensor::<f32>::new(&[3, 3, 3]).freeze();
    ///
    /// assert_eq!(a.get_index(&[2, 2, 2]), 26);
    /// assert_eq!(a.get_index(&[1, 2, 2]), 17);
    /// assert_eq!(a.get_index(&[1, 2, 0]), 15);
    /// assert_eq!(a.get_index(&[1, 0, 1]), 10);
    /// ```
    pub fn get_index(&self, indices: &[u64]) -> usize {
        assert!(self.dims.len() == indices.len());
        let mut index = 0;
        let mut d = 1;
        for i in (0..indices.len()).rev() {
            assert!(self.dims[i] > indices[i]);
            index += indices[i] * d;
            d *= self.dims[i];
        }
        index as usize
    }

    /// Returns the tensor's dimensions.
    pub fn dims(&self) -> &[u64] {
        &self.dims
    }

    /// Returns the tensor's dimensions as a Shape.
    pub fn shape(&self) -> Shape {
        Shape(Some(self.dims.iter().map(|d| Some(*d as i64)).collect()))
    }

    // Wraps a TF_Tensor. Returns None if types don't match.
    pub(super) unsafe fn from_tf_tensor(tensor: *mut tf::TF_Tensor) -> Option<Self> {
        let mut dims = Vec::with_capacity(tf::TF_NumDims(tensor) as usize);
        for i in 0..dims.capacity() {
            dims.push(tf::TF_Dim(tensor, i as c_int) as u64);
        }

        Some(Self {
            inner: T::InnerType::from_tf_tensor(tensor)?,
            dims,
        })
    }

    /// Convert back to a Tensor.
    ///
    /// Safety: This is unsafe because modifying the returned Tensor will modify the underlying memory,
    /// which may affect other Tensors that share the same memory.
    ///
    /// ```
    /// # use tensorflow::{Tensor, Result};
    /// # use tensorflow::eager::*;
    /// # fn main() -> Result<()> {
    /// let ctx = Context::new(ContextOptions::new())?;
    ///
    /// let a_readonly = Tensor::<i32>::new(&[2, 3, 5]).freeze();
    /// let h = a_readonly.to_handle(&ctx)?;
    /// let b_readonly = h.resolve::<i32>()?;
    ///
    /// let mut b = unsafe { b_readonly.into_tensor() };
    /// b[1*15 + 1*5 + 1] = 5;
    ///
    /// // Since a and b share the same memory, modifying b will also modify a.
    /// assert_eq!(a_readonly, b);
    /// # Ok(())
    /// # }
    /// ```
    pub unsafe fn into_tensor(self) -> Tensor<T> {
        Tensor {
            inner: self.inner,
            dims: self.dims,
        }
    }
}
<commit_msg>update doc<commit_after>use libc::c_int;
use std::ops::Deref;
use tensorflow_sys as tf;

use crate::{AnyTensor, DataType, Result, Shape, Tensor, TensorInner, TensorType};

/// A read-only tensor.
///
/// This ReadonlyTensor is a wrapper around a `Tensor` that is read-only.
/// Some operations that mutate the underlying Tensor are not supported.
#[derive(Debug, Clone, Eq)]
pub struct ReadonlyTensor<T: TensorType> {
    pub(super) inner: T::InnerType,
    pub(super) dims: Vec<u64>,
}

impl<T: TensorType> AnyTensor for ReadonlyTensor<T> {
    fn inner(&self) -> Result<*mut tf::TF_Tensor> {
        self.inner.as_mut_ptr(&self.dims)
    }

    fn data_type(&self) -> DataType {
        T::data_type()
    }
}

impl<T: TensorType> Deref for ReadonlyTensor<T> {
    type Target = [T];

    #[inline]
    fn deref(&self) -> &[T] {
        self.inner.deref()
    }
}

impl<T: TensorType + PartialEq> PartialEq for ReadonlyTensor<T> {
    fn eq(&self, other: &Self) -> bool {
        self.dims == other.dims && self.deref() == other.deref()
    }
}

impl<T: TensorType + PartialEq> PartialEq<Tensor<T>> for ReadonlyTensor<T> {
    fn eq(&self, other: &Tensor<T>) -> bool {
        self.dims == other.dims && self.deref() == other.deref()
    }
}

impl<T: TensorType> ReadonlyTensor<T> {
    /// Get one single value from the Tensor.
    ///
    /// ```
    /// # use tensorflow::Tensor;
    /// # use tensorflow::eager::ReadonlyTensor;
    /// let mut a = Tensor::<i32>::new(&[2, 3, 5]);
    ///
    /// a[1*15 + 1*5 + 1] = 5;
    /// let a = a.freeze();
    /// assert_eq!(a.get(&[1, 1, 1]), 5);
    /// ```
    pub fn get(&self, indices: &[u64]) -> T {
        let index = self.get_index(indices);
        self[index].clone()
    }

    /// Get the array index from rows / columns indices.
    ///
    /// ```
    /// # use tensorflow::Tensor;
    /// # use tensorflow::eager::ReadonlyTensor;
    /// let a = Tensor::<f32>::new(&[3, 3, 3]).freeze();
    ///
    /// assert_eq!(a.get_index(&[2, 2, 2]), 26);
    /// assert_eq!(a.get_index(&[1, 2, 2]), 17);
    /// assert_eq!(a.get_index(&[1, 2, 0]), 15);
    /// assert_eq!(a.get_index(&[1, 0, 1]), 10);
    /// ```
    pub fn get_index(&self, indices: &[u64]) -> usize {
        assert!(self.dims.len() == indices.len());
        let mut index = 0;
        let mut d = 1;
        for i in (0..indices.len()).rev() {
            assert!(self.dims[i] > indices[i]);
            index += indices[i] * d;
            d *= self.dims[i];
        }
        index as usize
    }

    /// Returns the tensor's dimensions.
    pub fn dims(&self) -> &[u64] {
        &self.dims
    }

    /// Returns the tensor's dimensions as a Shape.
    pub fn shape(&self) -> Shape {
        Shape(Some(self.dims.iter().map(|d| Some(*d as i64)).collect()))
    }

    // Wraps a TF_Tensor. Returns None if types don't match.
    pub(super) unsafe fn from_tf_tensor(tensor: *mut tf::TF_Tensor) -> Option<Self> {
        let mut dims = Vec::with_capacity(tf::TF_NumDims(tensor) as usize);
        for i in 0..dims.capacity() {
            dims.push(tf::TF_Dim(tensor, i as c_int) as u64);
        }

        Some(Self {
            inner: T::InnerType::from_tf_tensor(tensor)?,
            dims,
        })
    }

    /// Convert back to a Tensor.
    ///
    /// # Safety
    ///
    /// This is unsafe because modifying the returned Tensor will modify the underlying memory,
    /// which may affect other Tensors that share the same memory.
    ///
    /// ```
    /// # use tensorflow::{Tensor, Result};
    /// # use tensorflow::eager::*;
    /// # fn main() -> Result<()> {
    /// let ctx = Context::new(ContextOptions::new()).unwrap();
    /// let tensor = Tensor::from(0i32).freeze();
    /// let h = tensor.to_handle(&ctx).unwrap();
    ///
    /// let t0 = h.resolve::<i32>().unwrap();
    /// assert_eq!(t0[0], 0i32);
    ///
    /// // Manipulating the Tensor will affect the Tensor that shares underlying buffer.
    /// {
    ///     // Getting multiple times should return the same Tensor.
    ///     let t1 = h.resolve::<i32>().unwrap();
    ///
    ///     // Convert back from a TensorHandle to a Tensor.
    ///     let mut t1 = unsafe { t1.into_tensor() };
    ///     t1[0] = 5;
    /// }
    ///
    /// // Check that t0 shares the same underlying buffer with t1.
    /// // This is why we need to use unsafe.
    /// assert_eq!(t0[0], 5);
    /// # Ok(())
    /// # }
    /// ```
    pub unsafe fn into_tensor(self) -> Tensor<T> {
        Tensor {
            inner: self.inner,
            dims: self.dims,
        }
    }
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::ops::{self, UpdateOptions};
use cargo::util::print_available_packages;

pub fn cli() -> App {
    subcommand("update")
        .about("Update dependencies as recorded in the local lock file")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(opt("workspace", "Only update the workspace packages").short("w"))
        .arg_package_spec_simple("Package to update")
        .arg(opt(
            "aggressive",
            "Force updating all dependencies of <name> as well",
        ))
        .arg_dry_run("Don't actually write the lockfile")
        .arg(opt("precise", "Update a single dependency to exactly PRECISE").value_name("PRECISE"))
        .arg_manifest_path()
        .after_help("Run `cargo help update` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;

    if args.is_present_with_zero_values("package") {
        print_available_packages(&ws)?;
    }

    let update_opts = UpdateOptions {
        aggressive: args.is_present("aggressive"),
        precise: args.value_of("precise"),
        to_update: values(args, "package"),
        dry_run: args.is_present("dry-run"),
        workspace: args.is_present("workspace"),
        config,
    };
    ops::update_lockfile(&ws, &update_opts)?;
    Ok(())
}
<commit_msg>Clarify the help text of `--aggressive` and `--precise` of `cargo update`<commit_after>use crate::command_prelude::*;

use cargo::ops::{self, UpdateOptions};
use cargo::util::print_available_packages;

pub fn cli() -> App {
    subcommand("update")
        .about("Update dependencies as recorded in the local lock file")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(opt("workspace", "Only update the workspace packages").short("w"))
        .arg_package_spec_simple("Package to update")
        .arg(opt(
            "aggressive",
            "Force updating all dependencies of SPEC as well when used with -p",
        ))
        .arg_dry_run("Don't actually write the lockfile")
        .arg(
            opt(
                "precise",
                "Update a single dependency to exactly PRECISE when used with -p",
            )
            .value_name("PRECISE"),
        )
        .arg_manifest_path()
        .after_help("Run `cargo help update` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;

    if args.is_present_with_zero_values("package") {
        print_available_packages(&ws)?;
    }

    let update_opts = UpdateOptions {
        aggressive: args.is_present("aggressive"),
        precise: args.value_of("precise"),
        to_update: values(args, "package"),
        dry_run: args.is_present("dry-run"),
        workspace: args.is_present("workspace"),
        config,
    };
    ops::update_lockfile(&ws, &update_opts)?;
    Ok(())
}
<|endoftext|>


<commit_before>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;
use frame::subframe::{CodingMethod, PartitionedRiceContents};

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000            => constant(input, bits_per_sample),
    0b000001            => verbatim(input, bits_per_sample, block_size),
    0b001000...0b001100 => fixed(input, subframe_type & 0b0111,
                                 bits_per_sample, block_size),
    _                   => IResult::Error(Err::Position(
                             ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn fixed(input: (&[u8], usize),
         order: usize,
         bits_per_sample: usize,
         block_size: usize)
         -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup = [0; subframe::MAX_FIXED_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::Fixed(subframe::Fixed {
        entropy_coding_method: data.0,
        order: order as u8,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn coding_method(input: (&[u8], usize))
                 -> IResult<(&[u8], usize), CodingMethod> {
  match take_bits!(input, u8, 2) {
    IResult::Done(i, method)  => {
      match method {
        0 => IResult::Done(i, CodingMethod::PartitionedRice),
        1 => IResult::Done(i, CodingMethod::PartitionedRice2),
        _ => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0)),
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn residual(input: (&[u8], usize),
            predictor_order: usize,
            block_size: usize)
            -> IResult<(&[u8], usize),
                       (subframe::EntropyCodingMethod, Vec<i32>)> {
  match pair!(input, coding_method, take_bits!(u32, 4)) {
    IResult::Done(i, data)    => {
      let (method, order) = data;

      rice_partition(i, order, predictor_order, block_size, method)
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn rice_partition(input: (&[u8], usize),
                  partition_order: u32,
                  predictor_order: usize,
                  block_size: usize,
                  method: CodingMethod)
                  -> IResult<(&[u8], usize),
                             (subframe::EntropyCodingMethod, Vec<i32>)> {
  let (param_size, escape_code) = match method {
    CodingMethod::PartitionedRice  => (4, 0b1111),
    CodingMethod::PartitionedRice2 => (5, 0b11111),
  };

  // Adjust block size to not include allocation for warm up samples
  let residual_size = block_size - predictor_order;

  let mut mut_input = input;
  let mut residual  = Vec::with_capacity(residual_size);
  let mut sample    = 0;
  let mut contents  = PartitionedRiceContents::new(partition_order);

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

  for partition in 0..partitions {
    let offset = if partition_order == 0 {
      block_size - predictor_order
    } else if partition > 0 {
      block_size / partitions
    } else {
      (block_size / partitions) - predictor_order
    };
    let start = sample;
    let end   = sample + offset;

    let result = chain!(mut_input,
      rice_parameter: take_bits!(u32, param_size) ~
      size: cond!(rice_parameter == escape_code, take_bits!(usize, 5)) ~
      data: apply!(residual_data,
        size, rice_parameter,
        &mut contents.raw_bits[partition],
        &mut residual[start..end]
      ),
      || { rice_parameter }
    );

    match result {
      IResult::Done(i, parameter) => {
        mut_input = i;
        sample    = end;

        contents.parameters[partition] = parameter;
      }
      IResult::Error(error)       => return IResult::Error(error),
      IResult::Incomplete(need)   => return IResult::Incomplete(need),
    }
  }

  let entropy_coding_method = subframe::EntropyCodingMethod {
    method_type: method,
    data: subframe::PartitionedRice {
      order: partition_order,
      contents: contents,
    },
  };

  IResult::Done(mut_input, (entropy_coding_method, residual))
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<commit_msg>Add `qlp_coefficient_precision` parser<commit_after>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;
use frame::subframe::{CodingMethod, PartitionedRiceContents};

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000            => constant(input, bits_per_sample),
    0b000001            => verbatim(input, bits_per_sample, block_size),
    0b001000...0b001100 => fixed(input, subframe_type & 0b0111,
                                 bits_per_sample, block_size),
    _                   => IResult::Error(Err::Position(
                             ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn fixed(input: (&[u8], usize),
         order: usize,
         bits_per_sample: usize,
         block_size: usize)
         -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup = [0; subframe::MAX_FIXED_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::Fixed(subframe::Fixed {
        entropy_coding_method: data.0,
        order: order as u8,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn qlp_coefficient_precision(input: (&[u8], usize))
                             -> IResult<(&[u8], usize), u8> {
  match take_bits!(input, u8, 4) {
    IResult::Done(i, precision) => {
      if precision == 0b1111 {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      } else {
        IResult::Done(i, precision + 1)
      }
    }
    IResult::Error(error)       => IResult::Error(error),
    IResult::Incomplete(need)   => IResult::Incomplete(need),
  }
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn coding_method(input: (&[u8], usize))
                 -> IResult<(&[u8], usize), CodingMethod> {
  match take_bits!(input, u8, 2) {
    IResult::Done(i, method)  => {
      match method {
        0 => IResult::Done(i, CodingMethod::PartitionedRice),
        1 => IResult::Done(i, CodingMethod::PartitionedRice2),
        _ => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0)),
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn residual(input: (&[u8], usize),
            predictor_order: usize,
            block_size: usize)
            -> IResult<(&[u8], usize),
                       (subframe::EntropyCodingMethod, Vec<i32>)> {
  match pair!(input, coding_method, take_bits!(u32, 4)) {
    IResult::Done(i, data)    => {
      let (method, order) = data;

      rice_partition(i, order, predictor_order, block_size, method)
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn rice_partition(input: (&[u8], usize),
                  partition_order: u32,
                  predictor_order: usize,
                  block_size: usize,
                  method: CodingMethod)
                  -> IResult<(&[u8], usize),
                             (subframe::EntropyCodingMethod, Vec<i32>)> {
  let (param_size, escape_code) = match method {
    CodingMethod::PartitionedRice  => (4, 0b1111),
    CodingMethod::PartitionedRice2 => (5, 0b11111),
  };

  // Adjust block size to not include allocation for warm up samples
  let residual_size = block_size - predictor_order;

  let mut mut_input = input;
  let mut residual  = Vec::with_capacity(residual_size);
  let mut sample    = 0;
  let mut contents  = PartitionedRiceContents::new(partition_order);

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

  for partition in 0..partitions {
    let offset = if partition_order == 0 {
      block_size - predictor_order
    } else if partition > 0 {
      block_size / partitions
    } else {
      (block_size / partitions) - predictor_order
    };
    let start = sample;
    let end   = sample + offset;

    let result = chain!(mut_input,
      rice_parameter: take_bits!(u32, param_size) ~
      size: cond!(rice_parameter == escape_code, take_bits!(usize, 5)) ~
      data: apply!(residual_data,
        size, rice_parameter,
        &mut contents.raw_bits[partition],
        &mut residual[start..end]
      ),
      || { rice_parameter }
    );

    match result {
      IResult::Done(i, parameter) => {
        mut_input = i;
        sample    = end;

        contents.parameters[partition] = parameter;
      }
      IResult::Error(error)       => return IResult::Error(error),
      IResult::Incomplete(need)   => return IResult::Incomplete(need),
    }
  }

  let entropy_coding_method = subframe::EntropyCodingMethod {
    method_type: method,
    data: subframe::PartitionedRice {
      order: partition_order,
      contents: contents,
    },
  };

  IResult::Done(mut_input, (entropy_coding_method, residual))
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A bar that can used as a level indicator

use libc::c_double;

use gtk::{self, ffi};
use gtk::{LevelBarMode};
use gtk::cast::GTK_LEVELBAR;

/// LevelBar — A bar that can used as a level indicator
/*
* # Signal availables:
* * `offset-changed` : Has Details
*/
struct_Widget!(LevelBar);

impl LevelBar {
    pub fn new() -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new() };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn new_for_interval(min: f64, max: f64) -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new_for_interval(min as c_double, max as c_double) };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn set_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_value(GTK_LEVELBAR(self.pointer)) as f64
        }
    }

    pub fn set_mode(&mut self, mode: LevelBarMode) -> () {
        unsafe {
            ffi::gtk_level_bar_set_mode(GTK_LEVELBAR(self.pointer), mode);
        }
    }

    pub fn get_mode(&self) -> LevelBarMode {
        unsafe {
            ffi::gtk_level_bar_get_mode(GTK_LEVELBAR(self.pointer))
        }
    }

    pub fn set_min_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_min_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_min_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_min_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    pub fn set_max_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_max_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_max_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_max_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn set_inverted(&mut self, inverted: bool) -> () {
        match inverted {
            true    => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GTRUE) },
            false   => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GFALSE) }
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn get_inverted(&self) -> bool {
        match unsafe { ffi::gtk_level_bar_get_inverted(GTK_LEVELBAR(self.pointer)) } {
            ffi::GFALSE => false,
            _ => true
        }
    }

    pub fn add_offset_value(&mut self, name: &str, value: f64) -> () {
        unsafe {
            name.with_c_str(|c_str| {
                ffi::gtk_level_bar_add_offset_value(GTK_LEVELBAR(self.pointer), c_str, value as c_double)
            });
        }
    }

    pub fn remove_offset_value(&mut self, name: &str) -> () {
        unsafe {
            name.with_c_str(|c_str| {
                ffi::gtk_level_bar_remove_offset_value(GTK_LEVELBAR(self.pointer), c_str)
            });
        }
    }

    pub fn get_offset_value(&self, name: &str) -> Option<f64> {
        let value = 0.;
        match unsafe { name.with_c_str(|c_str| { ffi::gtk_level_bar_get_offset_value(GTK_LEVELBAR(self.pointer), c_str, &value) }) } {
            0132     => None,
            _        => Some(value)
        }
    }
}

impl_drop!(LevelBar);
impl_TraitWidget!(LevelBar);

impl gtk::OrientableTrait for LevelBar {}

impl_widget_events!(LevelBar);
<commit_msg>Add forgotten file<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A bar that can used as a level indicator

use libc::c_double;
use use std::c_str::ToCStr;

use gtk::{self, ffi};
use gtk::{LevelBarMode};
use gtk::cast::GTK_LEVELBAR;

/// LevelBar — A bar that can used as a level indicator
/*
* # Signal availables:
* * `offset-changed` : Has Details
*/
struct_Widget!(LevelBar);

impl LevelBar {
    pub fn new() -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new() };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn new_for_interval(min: f64, max: f64) -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new_for_interval(min as c_double, max as c_double) };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn set_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_value(GTK_LEVELBAR(self.pointer)) as f64
        }
    }

    pub fn set_mode(&mut self, mode: LevelBarMode) -> () {
        unsafe {
            ffi::gtk_level_bar_set_mode(GTK_LEVELBAR(self.pointer), mode);
        }
    }

    pub fn get_mode(&self) -> LevelBarMode {
        unsafe {
            ffi::gtk_level_bar_get_mode(GTK_LEVELBAR(self.pointer))
        }
    }

    pub fn set_min_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_min_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_min_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_min_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    pub fn set_max_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_max_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_max_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_max_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn set_inverted(&mut self, inverted: bool) -> () {
        match inverted {
            true    => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GTRUE) },
            false   => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GFALSE) }
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn get_inverted(&self) -> bool {
        match unsafe { ffi::gtk_level_bar_get_inverted(GTK_LEVELBAR(self.pointer)) } {
            ffi::GFALSE => false,
            _ => true
        }
    }

    pub fn add_offset_value(&mut self, name: &str, value: f64) -> () {
        unsafe {
            name.with_c_str(|c_str| {
                ffi::gtk_level_bar_add_offset_value(GTK_LEVELBAR(self.pointer), c_str, value as c_double)
            });
        }
    }

    pub fn remove_offset_value(&mut self, name: &str) -> () {
        unsafe {
            name.with_c_str(|c_str| {
                ffi::gtk_level_bar_remove_offset_value(GTK_LEVELBAR(self.pointer), c_str)
            });
        }
    }

    pub fn get_offset_value(&self, name: &str) -> Option<f64> {
        let value = 0.;
        match unsafe { name.with_c_str(|c_str| { ffi::gtk_level_bar_get_offset_value(GTK_LEVELBAR(self.pointer), c_str, &value) }) } {
            0132     => None,
            _        => Some(value)
        }
    }
}

impl_drop!(LevelBar);
impl_TraitWidget!(LevelBar);

impl gtk::OrientableTrait for LevelBar {}

impl_widget_events!(LevelBar);
<|endoftext|>


<commit_before>extern crate dft;
use dft::{Operation, Plan, Transform, c64};
use std::iter::FromIterator;
use std::f64::consts::PI;

fn main()
{
    let size: usize = 32;
    let planf        = Plan::new(dft::Operation::Forward, size);
    let plani        = Plan::new(dft::Operation::Inverse, size);
    let mut a        = Vec::from_iter ((0..size) .map(|idx| c64::new((idx+1) as f64, 0.0)));
    let mut kernel   = Vec::from_iter ((0..size) .map(|idx| c64::new( (2.0*PI * 3.0*(idx as f64) / (size as f64)).cos(),
                                                                      (2.0*PI * 3.0*(idx as f64) / (size as f64)).sin() )));
    println!("a: {:?}, kernel: {:?}", a, kernel);

    // forward Fourier transform
    a.transform(&planf);

    // convolution with the kernel
    let mut b        = Vec::from_iter ((0..size) .map(|i| a[i] * kernel[i]));

    b.transform(&plani);
    println!("b: {:?}", b);
}
<commit_msg>added comments.<commit_after>extern crate dft;
use dft::{Operation, Plan, Transform, c64};
use std::iter::FromIterator;
use std::f64::consts::PI;

fn main()
{
    let size: usize = 32;
    let planf        = Plan::new(dft::Operation::Forward, size);
    let plani        = Plan::new(dft::Operation::Inverse, size);
    let mut a        = Vec::from_iter ((0..size) .map(|idx| c64::new((idx+1) as f64, 0.0)));
    let mut kernel   = Vec::from_iter ((0..size) .map(|idx| c64::new( (2.0*PI * 3.0*(idx as f64) / (size as f64)).cos(),
                                                                      (2.0*PI * 3.0*(idx as f64) / (size as f64)).sin() )));
    println!("a: {:?}, kernel: {:?}", a, kernel);

    // forward Fourier transform
    a.transform(&planf);

    // convolution with the kernel
    let mut b        = Vec::from_iter ((0..size) .map(|i| a[i] * kernel[i]));

    // inverse Fourier transform
    b.transform(&plani);
    println!("b: {:?}", b);

    // expected cyclic shift:
    // a = [1, 2, 3, ...]
    // b = [4, 5, 6, ...]
}
<|endoftext|>