<commit_before>//! Type conversions for binding parameters and getting query results.

use super::{PreparedStatement, ResultRow,
            ColIx, ParamIx};
use super::{
    SqliteResult, SqliteErrorCode, SqliteError,
};
use super::ColumnType::SQLITE_NULL;

use std::error::FromError;

use time;

/// Values that can be bound to parameters in prepared statements.
pub trait ToSql {
    /// Bind the `ix`th parameter to this value (`self`).
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()>;
}

/// A trait for result values from a query.
///
/// cf [sqlite3 result values][column].
///
/// *inspired by sfackler's FromSql (and some haskell bindings?)*
///
/// [column]: http://www.sqlite.org/c3ref/column_blob.html
///
///   - *TODO: consider a `types` submodule*
///   - *TODO: many more implementors, including Option<T>*
pub trait FromSql {
    /// Try to extract a `Self` type value from the `col`th colum of a `ResultRow`.
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Self>;
}

impl ToSql for i32 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, *self)
    }
}

impl FromSql for i32 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i32> { Ok(row.column_int(col)) }
}

impl ToSql for i64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix, *self)
    }
}

impl FromSql for i64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i64> { Ok(row.column_int64(col)) }
}

impl ToSql for f64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_double(ix, *self)
    }
}

impl FromSql for f64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<f64> { Ok(row.column_double(col)) }
}

impl<T: ToSql + Clone> ToSql for Option<T> {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        match (*self).clone() {
            Some(x) => x.to_sql(s, ix),
            None => s.bind_null(ix)
        }
    }
}

impl<T: FromSql + Clone> FromSql for Option<T> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Option<T>> {
        match row.column_type(col) {
            SQLITE_NULL => Ok(None),
            _ => FromSql::from_sql(row, col).map(|x| Some(x))
        }
    }
}

impl ToSql for String {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_text(ix, (*self).as_ref())
    }
}

impl FromSql for String {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<String> {
        Ok(row.column_text(col).unwrap_or(String::new()))
    }
}

impl<'a> ToSql for &'a [u8] {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_blob(ix, *self)
    }
}

impl FromSql for Vec<u8> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Vec<u8>> {
        Ok(row.column_blob(col).unwrap_or(Vec::new()))
    }
}

/// Format of sqlite date strings
///
/// From [Date And Time Functions][lang_datefunc]:
/// > The datetime() function returns "YYYY-MM-DD HH:MM:SS"
/// [lang_datefunc]: http://www.sqlite.org/lang_datefunc.html
pub static SQLITE_TIME_FMT: &'static str = "%F %T";

impl FromSql for time::Tm {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Tm> {
        let txt = row.column_text(col).unwrap_or(String::new());
        Ok( try!(time::strptime(txt.as_ref(), SQLITE_TIME_FMT)) )
    }
}

impl FromError<time::ParseError> for SqliteError {
    fn from_error(err: time::ParseError) -> SqliteError {
        SqliteError {
            kind: SqliteErrorCode::SQLITE_MISMATCH,
            desc: "Time did not match expected format",
            detail: Some(format!("Time parsing error: {}", err)),
        }
    }
}

impl ToSql for time::Timespec {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        let timestr = time::at_utc(*self).strftime(SQLITE_TIME_FMT)
            .unwrap() // unit tests ensure SQLITE_TIME_FMT is ok
            .to_string();
        s.bind_text(ix, timestr.as_ref())
    }
}

impl FromSql for time::Timespec {
    /// TODO: propagate error message
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Timespec> {
        let tmo: SqliteResult<time::Tm> = FromSql::from_sql(row, col);
        tmo.map(|tm| tm.to_timespec())
    }
}

#[cfg(test)]
mod tests {
    use time::Tm;
    use super::super::{DatabaseConnection, SqliteResult, ResultSet};
    use super::super::{ResultRowAccess};

    fn with_query<T, F>(sql: &str, mut f: F) -> SqliteResult<T>
        where F: FnMut(&mut ResultSet) -> T
    {
        let db = try!(DatabaseConnection::in_memory());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn get_tm() {
        fn go() -> SqliteResult<()> {
            let conn = try!(DatabaseConnection::in_memory());
            let mut stmt = try!(
                conn.prepare("select datetime('2001-01-01', 'weekday 3', '3 hours')"));
            let mut results = stmt.execute();
            match results.step() {
                Ok(Some(ref mut row)) => {
                    assert_eq!(
                        row.get::<u32, Tm>(0),
                        Tm { tm_sec: 0,
                             tm_min: 0,
                             tm_hour: 3,
                             tm_mday: 3,
                             tm_mon: 0,
                             tm_year: 101,
                             tm_wday: 0,
                             tm_yday: 0,
                             tm_isdst: 0,
                             tm_utcoff: 0,
                             tm_nsec: 0
                        });
                    Ok(())
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            }
        }
        go().unwrap();
    }

    #[test]
    fn get_invalid_tm() {
        with_query("select 'not a time'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Tm> = row.get_opt(0u32);
                    assert!(x.is_err());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }

    #[test]
    fn select_blob() {
        with_query("select x'ff0db0'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Vec<u8>> = row.get_opt(0u32);
                    assert_eq!(x.ok().unwrap(), [0xff, 0x0d, 0xb0].to_vec());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }
}

// Local Variables:
// flycheck-rust-crate-root: "lib.rs"
// End:
<commit_msg>Implement ToSql/FromSql for bool<commit_after>//! Type conversions for binding parameters and getting query results.

use super::{PreparedStatement, ResultRow,
            ColIx, ParamIx};
use super::{
    SqliteResult, SqliteErrorCode, SqliteError,
};
use super::ColumnType::SQLITE_NULL;

use std::error::FromError;

use time;

/// Values that can be bound to parameters in prepared statements.
pub trait ToSql {
    /// Bind the `ix`th parameter to this value (`self`).
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()>;
}

/// A trait for result values from a query.
///
/// cf [sqlite3 result values][column].
///
/// *inspired by sfackler's FromSql (and some haskell bindings?)*
///
/// [column]: http://www.sqlite.org/c3ref/column_blob.html
///
///   - *TODO: consider a `types` submodule*
///   - *TODO: many more implementors, including Option<T>*
pub trait FromSql {
    /// Try to extract a `Self` type value from the `col`th colum of a `ResultRow`.
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Self>;
}

impl ToSql for i32 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, *self)
    }
}

impl FromSql for i32 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i32> { Ok(row.column_int(col)) }
}

impl ToSql for i64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix, *self)
    }
}

impl FromSql for i64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i64> { Ok(row.column_int64(col)) }
}

impl ToSql for f64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_double(ix, *self)
    }
}

impl FromSql for f64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<f64> { Ok(row.column_double(col)) }
}

impl ToSql for bool {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, if *self { 1 } else { 0 })
    }
}

impl FromSql for bool {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<bool> { Ok(row.column_int(col)!=0) }
}

impl<T: ToSql + Clone> ToSql for Option<T> {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        match (*self).clone() {
            Some(x) => x.to_sql(s, ix),
            None => s.bind_null(ix)
        }
    }
}

impl<T: FromSql + Clone> FromSql for Option<T> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Option<T>> {
        match row.column_type(col) {
            SQLITE_NULL => Ok(None),
            _ => FromSql::from_sql(row, col).map(|x| Some(x))
        }
    }
}

impl ToSql for String {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_text(ix, (*self).as_ref())
    }
}

impl FromSql for String {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<String> {
        Ok(row.column_text(col).unwrap_or(String::new()))
    }
}

impl<'a> ToSql for &'a [u8] {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_blob(ix, *self)
    }
}

impl FromSql for Vec<u8> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Vec<u8>> {
        Ok(row.column_blob(col).unwrap_or(Vec::new()))
    }
}

/// Format of sqlite date strings
///
/// From [Date And Time Functions][lang_datefunc]:
/// > The datetime() function returns "YYYY-MM-DD HH:MM:SS"
/// [lang_datefunc]: http://www.sqlite.org/lang_datefunc.html
pub static SQLITE_TIME_FMT: &'static str = "%F %T";

impl FromSql for time::Tm {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Tm> {
        let txt = row.column_text(col).unwrap_or(String::new());
        Ok( try!(time::strptime(txt.as_ref(), SQLITE_TIME_FMT)) )
    }
}

impl FromError<time::ParseError> for SqliteError {
    fn from_error(err: time::ParseError) -> SqliteError {
        SqliteError {
            kind: SqliteErrorCode::SQLITE_MISMATCH,
            desc: "Time did not match expected format",
            detail: Some(format!("Time parsing error: {}", err)),
        }
    }
}

impl ToSql for time::Timespec {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        let timestr = time::at_utc(*self).strftime(SQLITE_TIME_FMT)
            .unwrap() // unit tests ensure SQLITE_TIME_FMT is ok
            .to_string();
        s.bind_text(ix, timestr.as_ref())
    }
}

impl FromSql for time::Timespec {
    /// TODO: propagate error message
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Timespec> {
        let tmo: SqliteResult<time::Tm> = FromSql::from_sql(row, col);
        tmo.map(|tm| tm.to_timespec())
    }
}

#[cfg(test)]
mod tests {
    use time::Tm;
    use super::super::{DatabaseConnection, SqliteResult, ResultSet};
    use super::super::{ResultRowAccess};

    fn with_query<T, F>(sql: &str, mut f: F) -> SqliteResult<T>
        where F: FnMut(&mut ResultSet) -> T
    {
        let db = try!(DatabaseConnection::in_memory());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn get_tm() {
        fn go() -> SqliteResult<()> {
            let conn = try!(DatabaseConnection::in_memory());
            let mut stmt = try!(
                conn.prepare("select datetime('2001-01-01', 'weekday 3', '3 hours')"));
            let mut results = stmt.execute();
            match results.step() {
                Ok(Some(ref mut row)) => {
                    assert_eq!(
                        row.get::<u32, Tm>(0),
                        Tm { tm_sec: 0,
                             tm_min: 0,
                             tm_hour: 3,
                             tm_mday: 3,
                             tm_mon: 0,
                             tm_year: 101,
                             tm_wday: 0,
                             tm_yday: 0,
                             tm_isdst: 0,
                             tm_utcoff: 0,
                             tm_nsec: 0
                        });
                    Ok(())
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            }
        }
        go().unwrap();
    }

    #[test]
    fn get_invalid_tm() {
        with_query("select 'not a time'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Tm> = row.get_opt(0u32);
                    assert!(x.is_err());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }

    #[test]
    fn select_blob() {
        with_query("select x'ff0db0'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Vec<u8>> = row.get_opt(0u32);
                    assert_eq!(x.ok().unwrap(), [0xff, 0x0d, 0xb0].to_vec());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }
}

// Local Variables:
// flycheck-rust-crate-root: "lib.rs"
// End:
<|endoftext|>


<commit_before>#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowMenu {
    None,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AlertSeverity {
	Info,
	Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
	Plain(String),
	LabelDescription(String, String),
}<commit_msg>Warning alert<commit_after>#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowMenu {
    None,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AlertSeverity {
	Info,
	Warning,
	Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
	Plain(String),
	LabelDescription(String, String),
}<|endoftext|>


<commit_before>use std::fmt;
use std::io::Read;

use decoder::{decode, DecodedMap};
use errors::{Result, Error};

/// Represents a raw token
///
/// Raw tokens are used internally to represent the sourcemap
/// in a memory efficient way.  If you construct sourcemaps yourself
/// then you need to create these objects, otherwise they are invisible
/// to you as a user.
#[derive(PartialEq, Copy, Clone)]
pub struct RawToken {
    /// the destination (minified) line number
    pub dst_line: u32,
    /// the destination (minified) column number
    pub dst_col: u32,
    /// the source line number
    pub src_line: u32,
    /// the source line column
    pub src_col: u32,
    /// source identifier
    pub src_id: u32,
    /// name identifier (`!0` in case there is no associated name)
    pub name_id: u32,
}

/// Represents a token from a sourcemap
pub struct Token<'a> {
    raw: &'a RawToken,
    i: &'a SourceMap,
}

impl<'a> Token<'a> {
    /// get the destination (minified) line number
    pub fn get_dst_line(&self) -> u32 {
        self.raw.dst_line
    }

    /// get the destination (minified) column number
    pub fn get_dst_col(&self) -> u32 {
        self.raw.dst_col
    }

    /// get the destination line and column
    pub fn get_dst(&self) -> (u32, u32) {
        (self.get_dst_line(), self.get_dst_col())
    }

    /// get the source line number
    pub fn get_src_line(&self) -> u32 {
        self.raw.src_line
    }

    /// get the source column number
    pub fn get_src_col(&self) -> u32 {
        self.raw.src_col
    }

    /// get the source line and column
    pub fn get_src(&self) -> (u32, u32) {
        (self.get_src_line(), self.get_src_col())
    }

    /// get the source if it exists as string
    pub fn get_source(&self) -> &str {
        if self.raw.src_id == !0 {
            ""
        } else {
            &self.i.sources[self.raw.src_id as usize][..]
        }
    }

    /// get the name if it exists as string
    pub fn get_name(&self) -> Option<&str> {
        if self.raw.name_id == !0 {
            None
        } else {
            Some(&self.i.names[self.raw.name_id as usize][..])
        }
    }

    /// returns `true` if a name exists, `false` otherwise
    pub fn has_name(&self) -> bool {
        self.get_name().is_some()
    }

    /// Converts the token into a debug tuple in the form
    /// `(source, src_line, src_col, name)`
    pub fn to_tuple(&self) -> (&str, u32, u32, Option<&str>) {
        (
            self.get_source(),
            self.get_src_line(),
            self.get_src_col(),
            self.get_name()
        )
    }

    /// Get the underlying raw token
    pub fn get_raw_token(&self) -> RawToken {
        *self.raw
    }
}

/// Iterates over all tokens in a sourcemap
pub struct TokenIter<'a> {
    i: &'a SourceMap,
    next_idx: u32,
}

impl<'a> Iterator for TokenIter<'a> {
    type Item = Token<'a>;

    fn next(&mut self) -> Option<Token<'a>> {
        self.i.get_token(self.next_idx).map(|tok| {
            self.next_idx += 1;
            tok
        })
    }
}

/// Iterates over all index items in a sourcemap
pub struct IndexIter<'a> {
    i: &'a SourceMap,
    next_idx: usize,
}

impl<'a> Iterator for IndexIter<'a> {
    type Item = (u32, u32, u32);

    fn next(&mut self) -> Option<(u32, u32, u32)> {
        self.i.index.get(self.next_idx).map(|idx| {
            self.next_idx += 1;
            *idx
        })
    }
}

impl<'a> fmt::Debug for Token<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Token {}>", self)
    }
}

impl<'a> fmt::Display for Token<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}:{}{}",
               self.get_source(),
               self.get_src_line(),
               self.get_src_col(),
               self.get_name().map(|x| format!(" name={}", x))
                   .unwrap_or("".into()))
    }
}

/// Represents a section in a sourcemap index
pub struct SourceMapSection {
    offset: (u32, u32),
    url: Option<String>,
    map: Option<Box<SourceMap>>,
}

/// Iterates over all sections in a sourcemap index
pub struct SourceMapSectionIter<'a> {
    i: &'a SourceMapIndex,
    next_idx: u32,
}

impl<'a> Iterator for SourceMapSectionIter<'a> {
    type Item = &'a SourceMapSection;

    fn next(&mut self) -> Option<&'a SourceMapSection> {
        self.i.get_section(self.next_idx).map(|sec| {
            self.next_idx += 1;
            sec
        })
    }
}

/// Represents a sourcemap index in memory
pub struct SourceMapIndex {
    version: u32,
    file: Option<String>,
    sections: Vec<SourceMapSection>,
}

/// Represents a sourcemap in memory
///
/// This is always represents a regular "non-indexed" sourcemap.  Particularly
/// in case the `from_reader` method is used an index sourcemap will be
/// rejected with an error on reading.
pub struct SourceMap {
    version: u32,
    file: Option<String>,
    tokens: Vec<RawToken>,
    index: Vec<(u32, u32, u32)>,
    names: Vec<String>,
    sources: Vec<String>,
    sources_content: Vec<Option<String>>,
}

impl SourceMap {

    /// Creates a sourcemap from a reader over a JSON stream in UTF-8
    /// format.  Optionally a "garbage header" as defined by the
    /// sourcemap draft specification is supported.  In case an indexed
    /// sourcemap is encountered an error is returned.
    ///
    /// ```rust
    /// use sourcemap::SourceMap;
    /// let input: &[_] = b"{
    ///     \"version\":3,
    ///     \"sources\":[\"coolstuff.js\"],
    ///     \"names\":[\"x\",\"alert\"],
    ///     \"mappings\":\"AAAA,GAAIA,GAAI,EACR,IAAIA,GAAK,EAAG,CACVC,MAAM\"
    /// }";
    /// let sm = SourceMap::from_reader(input).unwrap();
    /// ```
    pub fn from_reader<R: Read>(rdr: R) -> Result<SourceMap> {
        match try!(decode(rdr)) {
            DecodedMap::Regular(sm) => Ok(sm),
            DecodedMap::Index(_) => Err(Error::IndexedSourcemap),
        }
    }

    /// Constructs a new sourcemap from raw components.
    ///
    /// - `version`: the version is typically `3` which is the current darft version
    /// - `file`: an optional filename of the sourcemap
    /// - `tokens`: a list of raw tokens
    /// - `index`: a sorted mapping of line and column to token index
    /// - `names`: a vector of names
    /// - `sources` a vector of source filenames
    /// - `sources_content` optional source contents
    pub fn new(version: u32, file: Option<String>, tokens: Vec<RawToken>,
               index: Vec<(u32, u32, u32)>, names: Vec<String>,
               sources: Vec<String>,
               sources_content: Option<Vec<Option<String>>>) -> SourceMap {
        SourceMap {
            version: version,
            file: file,
            tokens: tokens,
            index: index,
            names: names,
            sources: sources,
            sources_content: sources_content.unwrap_or(vec![]),
        }
    }

    /// Returns the version of the sourcemap.
    pub fn get_version(&self) -> u32 {
        self.version
    }

    /// Returns the embedded filename in case there is one.
    pub fn get_file(&self) -> Option<&str> {
        self.file.as_ref().map(|x| &x[..])
    }

    /// Looks up a token by its index.
    pub fn get_token<'a>(&'a self, idx: u32) -> Option<Token<'a>> {
        self.tokens.get(idx as usize).map(|raw| {
            Token { raw: raw, i: self }
        })
    }

    /// Returns the number of tokens in the sourcemap.
    pub fn get_token_count(&self) -> u32 {
        self.tokens.len() as u32
    }

    /// Returns an iterator over the tokens.
    pub fn tokens<'a>(&'a self) -> TokenIter<'a> {
        TokenIter { i: self, next_idx: 0 }
    }

    /// Looks up the closest token to a given line and column.
    pub fn lookup_token<'a>(&'a self, line: u32, col: u32) -> Option<Token<'a>> {
        let mut low = 0;
        let mut high = self.index.len();

        while low < high {
            let mid = (low + high) / 2;
            if (line, col, 0) < self.index[mid as usize] {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        if low > 0 {
            self.get_token(self.index[low as usize].2)
        } else {
            None
        }
    }

    /// Returns the number of sources in the sourcemap.
    pub fn get_source_count(&self) -> u32 {
        self.sources.len() as u32
    }

    /// Looks up a source for a specific index.
    pub fn get_source(&self, idx: u32) -> Option<&str> {
        self.sources.get(idx as usize).map(|x| &x[..])
    }

    /// Looks up the content for a source.
    pub fn get_source_contents(&self, idx: u32) -> Option<&str> {
        self.sources_content.get(idx as usize)
            .and_then(|bucket| bucket.as_ref()).map(|x| &**x)
    }

    /// Returns the number of names in the sourcemap.
    pub fn get_name_count(&self) -> u32 {
        self.names.len() as u32
    }

    /// Looks up a name for a specific index.
    pub fn get_name(&self, idx: u32) -> Option<&str> {
        self.names.get(idx as usize).map(|x| &x[..])
    }

    /// Returns the number of items in the index
    pub fn get_index_size(&self) -> usize {
        self.index.len()
    }

    /// Returns the number of items in the index
    pub fn index_iter<'a>(&'a self) -> IndexIter<'a> {
        IndexIter { i: self, next_idx: 0 }
    }
}

impl SourceMapIndex {

    /// Creates a sourcemap index from a reader over a JSON stream in UTF-8
    /// format.  Optionally a "garbage header" as defined by the
    /// sourcemap draft specification is supported.  In case a regular
    /// sourcemap is encountered an error is returned.
    pub fn from_reader<R: Read>(rdr: R) -> Result<SourceMapIndex> {
        match try!(decode(rdr)) {
            DecodedMap::Regular(_) => Err(Error::RegularSourcemap),
            DecodedMap::Index(smi) => Ok(smi),
        }
    }

    /// Constructs a new sourcemap index from raw components.
    ///
    /// - `version`: the version is typically `3` which is the current darft version
    /// - `file`: an optional filename of the index
    /// - `sections`: a vector of source map index sections
    pub fn new(version: u32, file: Option<String>,
               sections: Vec<SourceMapSection>) -> SourceMapIndex {
        SourceMapIndex {
            version: version,
            file: file,
            sections: sections,
        }
    }

    /// Returns the version of the sourcemap index.
    pub fn get_version(&self) -> u32 {
        self.version
    }

    /// Returns the embedded filename in case there is one.
    pub fn get_file(&self) -> Option<&str> {
        self.file.as_ref().map(|x| &x[..])
    }

    /// Returns the number of sections in this index
    pub fn get_section_count(&self) -> u32 {
        self.sections.len() as u32
    }

    /// Looks up a single section and returns it
    pub fn get_section(&self, idx: u32) -> Option<&SourceMapSection> {
        self.sections.get(idx as usize)
    }

    /// Looks up a single section and returns it as a mutable ref
    pub fn get_section_mut(&mut self, idx: u32) -> Option<&mut SourceMapSection> {
        self.sections.get_mut(idx as usize)
    }

    /// Iterates over all sections
    pub fn sections<'a>(&'a self) -> SourceMapSectionIter<'a> {
        SourceMapSectionIter {
            i: self,
            next_idx: 0
        }
    }

    /// Looks up the closest token to a given line and column.
    ///
    /// This requires that the referenced sourcemaps are actually loaded.
    /// If a sourcemap is encountered that is not embedded but just
    /// externally referenced it is silently skipped.
    pub fn lookup_token<'a>(&'a self, line: u32, col: u32) -> Option<Token<'a>> {
        for section in self.sections() {
            let (off_line, off_col) = section.get_offset();
            if off_line < line || off_col < col {
                continue;
            }
            if let Some(map) = section.get_sourcemap() {
                if let Some(tok) = map.lookup_token(line - off_line, col - off_col) {
                    return Some(tok);
                }
            }
        }
        None
    }
}

impl SourceMapSection {

    /// Create a new sourcemap index section
    ///
    /// - `offset`: offset as line and column
    /// - `url`: optional URL of where the sourcemap is located
    /// - `map`: an optional already resolved internal sourcemap
    pub fn new(offset: (u32, u32), url: Option<String>, map: Option<SourceMap>) -> SourceMapSection {
        SourceMapSection {
            offset: offset,
            url: url,
            map: map.map(|x| Box::new(x)),
        }
    }

    /// Returns the offset line
    pub fn get_offset_line(&self) -> u32 {
        self.offset.0
    }

    /// Returns the offset column
    pub fn get_offset_col(&self) -> u32 {
        self.offset.1
    }

    /// Returns the offset as tuple
    pub fn get_offset(&self) -> (u32, u32) {
        self.offset
    }

    /// Returns the URL of the referenced map if available
    pub fn get_url(&self) -> Option<&str> {
        self.url.as_ref().map(|x| &**x)
    }

    /// Returns a reference to the embedded sourcemap if available
    pub fn get_sourcemap(&self) -> Option<&SourceMap> {
        self.map.as_ref().map(|x| &**x)
    }

    /// Replaces the embedded sourcemap
    pub fn set_sourcemap(&mut self, sm: SourceMap) {
        self.map = Some(Box::new(sm));
    }
}
<commit_msg>Added support to return source id from token<commit_after>use std::fmt;
use std::io::Read;

use decoder::{decode, DecodedMap};
use errors::{Result, Error};

/// Represents a raw token
///
/// Raw tokens are used internally to represent the sourcemap
/// in a memory efficient way.  If you construct sourcemaps yourself
/// then you need to create these objects, otherwise they are invisible
/// to you as a user.
#[derive(PartialEq, Copy, Clone)]
pub struct RawToken {
    /// the destination (minified) line number
    pub dst_line: u32,
    /// the destination (minified) column number
    pub dst_col: u32,
    /// the source line number
    pub src_line: u32,
    /// the source line column
    pub src_col: u32,
    /// source identifier
    pub src_id: u32,
    /// name identifier (`!0` in case there is no associated name)
    pub name_id: u32,
}

/// Represents a token from a sourcemap
pub struct Token<'a> {
    raw: &'a RawToken,
    i: &'a SourceMap,
}

impl<'a> Token<'a> {
    /// get the destination (minified) line number
    pub fn get_dst_line(&self) -> u32 {
        self.raw.dst_line
    }

    /// get the destination (minified) column number
    pub fn get_dst_col(&self) -> u32 {
        self.raw.dst_col
    }

    /// get the destination line and column
    pub fn get_dst(&self) -> (u32, u32) {
        (self.get_dst_line(), self.get_dst_col())
    }

    /// get the source line number
    pub fn get_src_line(&self) -> u32 {
        self.raw.src_line
    }

    /// get the source column number
    pub fn get_src_col(&self) -> u32 {
        self.raw.src_col
    }

    /// get the source line and column
    pub fn get_src(&self) -> (u32, u32) {
        (self.get_src_line(), self.get_src_col())
    }

    /// get the source if it exists as string
    pub fn get_source(&self) -> &str {
        if self.raw.src_id == !0 {
            ""
        } else {
            &self.i.sources[self.raw.src_id as usize][..]
        }
    }

    /// get the source ID if it exists
    pub fn get_source_id(&self) -> Option<u32> {
        if self.raw.src_id == !0 {
            None
        } else {
            Some(self.raw.src_id)
        }
    }

    /// get the name if it exists as string
    pub fn get_name(&self) -> Option<&str> {
        if self.raw.name_id == !0 {
            None
        } else {
            Some(&self.i.names[self.raw.name_id as usize][..])
        }
    }

    /// returns `true` if a name exists, `false` otherwise
    pub fn has_name(&self) -> bool {
        self.get_name().is_some()
    }

    /// Converts the token into a debug tuple in the form
    /// `(source, src_line, src_col, name)`
    pub fn to_tuple(&self) -> (&str, u32, u32, Option<&str>) {
        (
            self.get_source(),
            self.get_src_line(),
            self.get_src_col(),
            self.get_name()
        )
    }

    /// Get the underlying raw token
    pub fn get_raw_token(&self) -> RawToken {
        *self.raw
    }
}

/// Iterates over all tokens in a sourcemap
pub struct TokenIter<'a> {
    i: &'a SourceMap,
    next_idx: u32,
}

impl<'a> Iterator for TokenIter<'a> {
    type Item = Token<'a>;

    fn next(&mut self) -> Option<Token<'a>> {
        self.i.get_token(self.next_idx).map(|tok| {
            self.next_idx += 1;
            tok
        })
    }
}

/// Iterates over all index items in a sourcemap
pub struct IndexIter<'a> {
    i: &'a SourceMap,
    next_idx: usize,
}

impl<'a> Iterator for IndexIter<'a> {
    type Item = (u32, u32, u32);

    fn next(&mut self) -> Option<(u32, u32, u32)> {
        self.i.index.get(self.next_idx).map(|idx| {
            self.next_idx += 1;
            *idx
        })
    }
}

impl<'a> fmt::Debug for Token<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Token {}>", self)
    }
}

impl<'a> fmt::Display for Token<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}:{}{}",
               self.get_source(),
               self.get_src_line(),
               self.get_src_col(),
               self.get_name().map(|x| format!(" name={}", x))
                   .unwrap_or("".into()))
    }
}

/// Represents a section in a sourcemap index
pub struct SourceMapSection {
    offset: (u32, u32),
    url: Option<String>,
    map: Option<Box<SourceMap>>,
}

/// Iterates over all sections in a sourcemap index
pub struct SourceMapSectionIter<'a> {
    i: &'a SourceMapIndex,
    next_idx: u32,
}

impl<'a> Iterator for SourceMapSectionIter<'a> {
    type Item = &'a SourceMapSection;

    fn next(&mut self) -> Option<&'a SourceMapSection> {
        self.i.get_section(self.next_idx).map(|sec| {
            self.next_idx += 1;
            sec
        })
    }
}

/// Represents a sourcemap index in memory
pub struct SourceMapIndex {
    version: u32,
    file: Option<String>,
    sections: Vec<SourceMapSection>,
}

/// Represents a sourcemap in memory
///
/// This is always represents a regular "non-indexed" sourcemap.  Particularly
/// in case the `from_reader` method is used an index sourcemap will be
/// rejected with an error on reading.
pub struct SourceMap {
    version: u32,
    file: Option<String>,
    tokens: Vec<RawToken>,
    index: Vec<(u32, u32, u32)>,
    names: Vec<String>,
    sources: Vec<String>,
    sources_content: Vec<Option<String>>,
}

impl SourceMap {

    /// Creates a sourcemap from a reader over a JSON stream in UTF-8
    /// format.  Optionally a "garbage header" as defined by the
    /// sourcemap draft specification is supported.  In case an indexed
    /// sourcemap is encountered an error is returned.
    ///
    /// ```rust
    /// use sourcemap::SourceMap;
    /// let input: &[_] = b"{
    ///     \"version\":3,
    ///     \"sources\":[\"coolstuff.js\"],
    ///     \"names\":[\"x\",\"alert\"],
    ///     \"mappings\":\"AAAA,GAAIA,GAAI,EACR,IAAIA,GAAK,EAAG,CACVC,MAAM\"
    /// }";
    /// let sm = SourceMap::from_reader(input).unwrap();
    /// ```
    pub fn from_reader<R: Read>(rdr: R) -> Result<SourceMap> {
        match try!(decode(rdr)) {
            DecodedMap::Regular(sm) => Ok(sm),
            DecodedMap::Index(_) => Err(Error::IndexedSourcemap),
        }
    }

    /// Constructs a new sourcemap from raw components.
    ///
    /// - `version`: the version is typically `3` which is the current darft version
    /// - `file`: an optional filename of the sourcemap
    /// - `tokens`: a list of raw tokens
    /// - `index`: a sorted mapping of line and column to token index
    /// - `names`: a vector of names
    /// - `sources` a vector of source filenames
    /// - `sources_content` optional source contents
    pub fn new(version: u32, file: Option<String>, tokens: Vec<RawToken>,
               index: Vec<(u32, u32, u32)>, names: Vec<String>,
               sources: Vec<String>,
               sources_content: Option<Vec<Option<String>>>) -> SourceMap {
        SourceMap {
            version: version,
            file: file,
            tokens: tokens,
            index: index,
            names: names,
            sources: sources,
            sources_content: sources_content.unwrap_or(vec![]),
        }
    }

    /// Returns the version of the sourcemap.
    pub fn get_version(&self) -> u32 {
        self.version
    }

    /// Returns the embedded filename in case there is one.
    pub fn get_file(&self) -> Option<&str> {
        self.file.as_ref().map(|x| &x[..])
    }

    /// Looks up a token by its index.
    pub fn get_token<'a>(&'a self, idx: u32) -> Option<Token<'a>> {
        self.tokens.get(idx as usize).map(|raw| {
            Token { raw: raw, i: self }
        })
    }

    /// Returns the number of tokens in the sourcemap.
    pub fn get_token_count(&self) -> u32 {
        self.tokens.len() as u32
    }

    /// Returns an iterator over the tokens.
    pub fn tokens<'a>(&'a self) -> TokenIter<'a> {
        TokenIter { i: self, next_idx: 0 }
    }

    /// Looks up the closest token to a given line and column.
    pub fn lookup_token<'a>(&'a self, line: u32, col: u32) -> Option<Token<'a>> {
        let mut low = 0;
        let mut high = self.index.len();

        while low < high {
            let mid = (low + high) / 2;
            if (line, col, 0) < self.index[mid as usize] {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        if low > 0 {
            self.get_token(self.index[low as usize].2)
        } else {
            None
        }
    }

    /// Returns the number of sources in the sourcemap.
    pub fn get_source_count(&self) -> u32 {
        self.sources.len() as u32
    }

    /// Looks up a source for a specific index.
    pub fn get_source(&self, idx: u32) -> Option<&str> {
        self.sources.get(idx as usize).map(|x| &x[..])
    }

    /// Looks up the content for a source.
    pub fn get_source_contents(&self, idx: u32) -> Option<&str> {
        self.sources_content.get(idx as usize)
            .and_then(|bucket| bucket.as_ref()).map(|x| &**x)
    }

    /// Returns the number of names in the sourcemap.
    pub fn get_name_count(&self) -> u32 {
        self.names.len() as u32
    }

    /// Looks up a name for a specific index.
    pub fn get_name(&self, idx: u32) -> Option<&str> {
        self.names.get(idx as usize).map(|x| &x[..])
    }

    /// Returns the number of items in the index
    pub fn get_index_size(&self) -> usize {
        self.index.len()
    }

    /// Returns the number of items in the index
    pub fn index_iter<'a>(&'a self) -> IndexIter<'a> {
        IndexIter { i: self, next_idx: 0 }
    }
}

impl SourceMapIndex {

    /// Creates a sourcemap index from a reader over a JSON stream in UTF-8
    /// format.  Optionally a "garbage header" as defined by the
    /// sourcemap draft specification is supported.  In case a regular
    /// sourcemap is encountered an error is returned.
    pub fn from_reader<R: Read>(rdr: R) -> Result<SourceMapIndex> {
        match try!(decode(rdr)) {
            DecodedMap::Regular(_) => Err(Error::RegularSourcemap),
            DecodedMap::Index(smi) => Ok(smi),
        }
    }

    /// Constructs a new sourcemap index from raw components.
    ///
    /// - `version`: the version is typically `3` which is the current darft version
    /// - `file`: an optional filename of the index
    /// - `sections`: a vector of source map index sections
    pub fn new(version: u32, file: Option<String>,
               sections: Vec<SourceMapSection>) -> SourceMapIndex {
        SourceMapIndex {
            version: version,
            file: file,
            sections: sections,
        }
    }

    /// Returns the version of the sourcemap index.
    pub fn get_version(&self) -> u32 {
        self.version
    }

    /// Returns the embedded filename in case there is one.
    pub fn get_file(&self) -> Option<&str> {
        self.file.as_ref().map(|x| &x[..])
    }

    /// Returns the number of sections in this index
    pub fn get_section_count(&self) -> u32 {
        self.sections.len() as u32
    }

    /// Looks up a single section and returns it
    pub fn get_section(&self, idx: u32) -> Option<&SourceMapSection> {
        self.sections.get(idx as usize)
    }

    /// Looks up a single section and returns it as a mutable ref
    pub fn get_section_mut(&mut self, idx: u32) -> Option<&mut SourceMapSection> {
        self.sections.get_mut(idx as usize)
    }

    /// Iterates over all sections
    pub fn sections<'a>(&'a self) -> SourceMapSectionIter<'a> {
        SourceMapSectionIter {
            i: self,
            next_idx: 0
        }
    }

    /// Looks up the closest token to a given line and column.
    ///
    /// This requires that the referenced sourcemaps are actually loaded.
    /// If a sourcemap is encountered that is not embedded but just
    /// externally referenced it is silently skipped.
    pub fn lookup_token<'a>(&'a self, line: u32, col: u32) -> Option<Token<'a>> {
        for section in self.sections() {
            let (off_line, off_col) = section.get_offset();
            if off_line < line || off_col < col {
                continue;
            }
            if let Some(map) = section.get_sourcemap() {
                if let Some(tok) = map.lookup_token(line - off_line, col - off_col) {
                    return Some(tok);
                }
            }
        }
        None
    }
}

impl SourceMapSection {

    /// Create a new sourcemap index section
    ///
    /// - `offset`: offset as line and column
    /// - `url`: optional URL of where the sourcemap is located
    /// - `map`: an optional already resolved internal sourcemap
    pub fn new(offset: (u32, u32), url: Option<String>, map: Option<SourceMap>) -> SourceMapSection {
        SourceMapSection {
            offset: offset,
            url: url,
            map: map.map(|x| Box::new(x)),
        }
    }

    /// Returns the offset line
    pub fn get_offset_line(&self) -> u32 {
        self.offset.0
    }

    /// Returns the offset column
    pub fn get_offset_col(&self) -> u32 {
        self.offset.1
    }

    /// Returns the offset as tuple
    pub fn get_offset(&self) -> (u32, u32) {
        self.offset
    }

    /// Returns the URL of the referenced map if available
    pub fn get_url(&self) -> Option<&str> {
        self.url.as_ref().map(|x| &**x)
    }

    /// Returns a reference to the embedded sourcemap if available
    pub fn get_sourcemap(&self) -> Option<&SourceMap> {
        self.map.as_ref().map(|x| &**x)
    }

    /// Replaces the embedded sourcemap
    pub fn set_sourcemap(&mut self, sm: SourceMap) {
        self.map = Some(Box::new(sm));
    }
}
<|endoftext|>


<commit_before>use std::{mem};

use num::{BigInt, One, Signed};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BitString {
    pub data: Vec<u8>,
    pub bit_length: usize,
}

impl BitString {
    pub fn new(data: Vec<u8>, bit_length: usize) -> Option<BitString> {
        // TODO: there's got to be a good way to simplify this.
        if data.is_empty() || bit_length == 0 {
            if !(data.is_empty() && bit_length == 0) {
                return None;
            }
        } else if (bit_length < (data.len() - 1) * 8) || (bit_length > data.len() * 8) {
            return None;
        }

        return Some(BitString{
            data: data,
            bit_length: bit_length,
        })
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer: Sized {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                } else if data.is_empty() {
                    return Err(DeserializationError::InvalidValue);
                }

                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        if self.is_positive() {
            let (_, mut bytes) = self.to_bytes_be();
            if bytes[0] & 0x80 == 0x80 {
                // If the data has a leading 0x80, pad with a zero-byte.
                bytes.insert(0, 0);
            }
            return bytes;
        } else if self.is_negative() {
            // Convert negative numbers to two's-complement by subtracting one and inverting.
            let n_minus_1 = -self - BigInt::one();
            let (_, mut bytes) = n_minus_1.to_bytes_be();

            for i in 0..bytes.len() {
                bytes[i] ^= 0xff;
            }

            if bytes[0] & 0x80 == 0 {
                bytes.insert(0, 0xff);
            }
            return bytes;
        } else {
            return b"\x00".to_vec();
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data.is_empty() {
            return Err(DeserializationError::InvalidValue);
        }

        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{BitString, ObjectIdentifier};

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }

    #[test]
    fn test_bit_string_new() {
        assert!(BitString::new(b"".to_vec(), 1).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 0).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 9).is_none());
    }
}
<commit_msg>simplify this code<commit_after>use std::{mem};

use num::{BigInt, One, Signed};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BitString {
    pub data: Vec<u8>,
    pub bit_length: usize,
}

impl BitString {
    pub fn new(data: Vec<u8>, bit_length: usize) -> Option<BitString> {
        match (data.len(), bit_length) {
            (0, 0) => (),
            (_, 0) | (0, _) => return None,
            (i, j) if (i * 8 < j) || (i - 1) * 8 > j  => return None,
            _ => (),
        }

        return Some(BitString{
            data: data,
            bit_length: bit_length,
        })
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer: Sized {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                } else if data.is_empty() {
                    return Err(DeserializationError::InvalidValue);
                }

                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        if self.is_positive() {
            let (_, mut bytes) = self.to_bytes_be();
            if bytes[0] & 0x80 == 0x80 {
                // If the data has a leading 0x80, pad with a zero-byte.
                bytes.insert(0, 0);
            }
            return bytes;
        } else if self.is_negative() {
            // Convert negative numbers to two's-complement by subtracting one and inverting.
            let n_minus_1 = -self - BigInt::one();
            let (_, mut bytes) = n_minus_1.to_bytes_be();

            for i in 0..bytes.len() {
                bytes[i] ^= 0xff;
            }

            if bytes[0] & 0x80 == 0 {
                bytes.insert(0, 0xff);
            }
            return bytes;
        } else {
            return b"\x00".to_vec();
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data.is_empty() {
            return Err(DeserializationError::InvalidValue);
        }

        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{BitString, ObjectIdentifier};

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }

    #[test]
    fn test_bit_string_new() {
        assert!(BitString::new(b"".to_vec(), 1).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 0).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 9).is_none());
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://urschrei.github.io/lonlat_bng/")]
//! This module provides utilities to the conversions module
use conversions::MIN_X_SHIFT;
use conversions::MIN_Y_SHIFT;
use conversions::MIN_Z_SHIFT;

use std;
use std::fmt;
use ostn02_phf::ostn02_lookup;

extern crate phf;
include!("hexkeys.rs");

// fn helmert(lon_vec: [&f64], lat_vec: [&f64]) -> (Vec<f64>, Vec<f64>) {
//     let t_array = Vec3::new(TX, TY, TZ);
//     let params = Mat3::new(1. + s, RZS, -RYS, -RZS, 1. + s, RXS, RYS, -RXS, 1. + s);
//     // let zeros: Vec<&f64> = vec![&1.; lon_vec.len()];
//     let test = vec![1, 2, 3, 4, 5, 6];
//     // let mut combined: Vec<&f64> = lon_vec.extend(lat_vec.iter()).collect();
//     // combined.extend(zeros.iter().cloned());
//     // let tmat = DMat::from_row_vec(3, zeros.len(), &combined);
//     let tmat = DMat::from_row_vec(3, 2, &test);
//     // build input vector of x, y, and z columns
//     // let inp = DMat::from_row_vec(3, 1, vec![lon_vec, lat_vec, h_vec]);
//     (vec![1.], vec![2.])
// }

/// Bounds checking for input values
pub fn check<T>(to_check: T, bounds: (T, T)) -> Result<T, ()>
    where T: std::cmp::PartialOrd + fmt::Display + Copy
{
    match to_check {
        to_check if bounds.0 <= to_check && to_check <= bounds.1 => Ok(to_check),
        _ => Err(()),
    }
}

/// Round Easting, Northing, and Orthometric height to the nearest millimetre
pub fn round_to_nearest_mm(x: f64, y: f64, z: f64) -> (f64, f64, f64) {
    let new_x = (x * 1000.).round() as f64 / 1000.;
    let new_y = (y * 1000.).round() as f64 / 1000.;
    let new_z = (z * 1000.).round() as f64 / 1000.;
    (new_x, new_y, new_z)
}

/// Round a float to nine decimal places
pub fn round_to_eight(x: f64, y: f64) -> (f64, f64) {
    let new_x = (x * 100000000.).round() as f64 / 100000000.;
    let new_y = (y * 100000000.).round() as f64 / 100000000.;
    (new_x, new_y)
}

/// Try to get OSTN02 shift parameters, and calculate offsets
pub fn get_ostn_ref(x: &i32, y: &i32) -> Result<(f64, f64, f64), ()> {
    // let key = format!("{:03x}{:03x}", y, x);
    // optimisation from https://github.com/hoodie/concatenation_benchmarks-rs
    let mut key = String::with_capacity(10);
    key.push_str(HEXKEYS.get(y).unwrap());
    key.push_str(HEXKEYS.get(x).unwrap());
    // Some or None, so convert to Result, which we can try!
    let result = try!(ostn02_lookup(&*key).ok_or(()));
    Ok((result.0 as f64 / 1000. + MIN_X_SHIFT,
        result.1 as f64 / 1000. + MIN_Y_SHIFT,
        result.2 as f64 / 1000. + MIN_Z_SHIFT))

}

// Input values must be valid ETRS89 grid references
// See p20 of the transformation user guide at
// https://www.ordnancesurvey.co.uk/business-and-government/help-and-support/navigation-technology/os-net/formats-for-developers.html
pub fn ostn02_shifts(x: &f64, y: &f64) -> Result<(f64, f64, f64), ()> {
    let e_index = (*x / 1000.) as i32;
    let n_index = (*y / 1000.) as i32;

    // eastings and northings of the south-west corner of the cell
    let x0 = e_index as i32 * 1000;
    let y0 = n_index as i32 * 1000;

    // The easting, northing and geoid shifts for the four corners of the cell
    // any of these could be Err, so use try!

    // bottom-left grid intersection
    let s0: (f64, f64, f64) = try!(get_ostn_ref(&(e_index), &(n_index)));
    // bottom-right
    let s1: (f64, f64, f64) = try!(get_ostn_ref(&(e_index + 1), &(n_index + 0)));
    // top-left
    let s2: (f64, f64, f64) = try!(get_ostn_ref(&(e_index + 0), &(n_index + 1)));
    // top-right
    let s3: (f64, f64, f64) = try!(get_ostn_ref(&(e_index + 1), &(n_index + 1)));

    // offset within square
    let dx = x - (x0 as f64);
    let dy = y - (y0 as f64);

    let t = dx / 1000.;
    let u = dy / 1000.;

    let f0 = (1. - t as f64) * (1. - u as f64);
    let f1 = t as f64 * (1. - u as f64);
    let f2 = (1. - t as f64) * u as f64;
    let f3 = t as f64 * u as f64;

    // bilinear interpolation, to obtain the actual shifts
    let se = f0 * s0.0 + f1 * s1.0 + f2 * s2.0 + f3 * s3.0;
    let sn = f0 * s0.1 + f1 * s1.1 + f2 * s2.1 + f3 * s3.1;
    let sg = f0 * s0.2 + f1 * s1.2 + f2 * s2.2 + f3 * s3.2;

    Ok(round_to_nearest_mm(se, sn, sg))

}

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

    #[test]
    // original coordinates are 651307.003, 313255.686
    fn test_ostn_hashmap_retrieval() {
        let eastings = 651;
        let northings = 313;
        let expected = (102.775, -78.244, 44.252);
        assert_eq!(expected, get_ostn_ref(&eastings, &northings).unwrap());
    }

    #[test]
    #[should_panic]
    fn test_failed_ostn_hashmap_retrieval() {
        // we're try!ing this in the shift calculation function, so an Err is fine
        let eastings = 999;
        let northings = 999;
        let expected = (1., 1., 1.);
        assert_eq!(expected, get_ostn_ref(&eastings, &northings).unwrap());
    }

    #[test]
    fn test_ostn02_shift_incorporation() {
        // these are the input values and corrections on p20-21
        let eastings = 651307.003;
        let northings = 313255.686;
        let expected = (102.789, -78.238, 44.244);
        assert_eq!(expected, ostn02_shifts(&eastings, &northings).unwrap());
    }

    #[test]
    #[should_panic]
    fn test_min_lon_extents() {
        let max_lon = 1.768960;
        let min_lon = -6.379880;
        // below min_lon
        check(&-6.379881, (&min_lon, &max_lon)).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_min_lat_extents() {
        let max_lat = 55.811741;
        let min_lat = 49.871159;
        // below min lat
        check(&49.871158, (&min_lat, &max_lat)).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_max_lon_extents() {
        let max_lon = 1.768960;
        let min_lon = -6.379880;
        // above max lon
        check(&1.768961, (&min_lon, &max_lon)).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_max_lat_extents() {
        let max_lat = 55.811741;
        let min_lat = 49.871159;
        // above max lat
        check(&55.811742, (&min_lat, &max_lat)).unwrap();
    }
}
<commit_msg>We need up to 8 chars<commit_after>#![doc(html_root_url = "https://urschrei.github.io/lonlat_bng/")]
//! This module provides utilities to the conversions module
use conversions::MIN_X_SHIFT;
use conversions::MIN_Y_SHIFT;
use conversions::MIN_Z_SHIFT;

use std;
use std::fmt;
use ostn02_phf::ostn02_lookup;

extern crate phf;
include!("hexkeys.rs");

// fn helmert(lon_vec: [&f64], lat_vec: [&f64]) -> (Vec<f64>, Vec<f64>) {
//     let t_array = Vec3::new(TX, TY, TZ);
//     let params = Mat3::new(1. + s, RZS, -RYS, -RZS, 1. + s, RXS, RYS, -RXS, 1. + s);
//     // let zeros: Vec<&f64> = vec![&1.; lon_vec.len()];
//     let test = vec![1, 2, 3, 4, 5, 6];
//     // let mut combined: Vec<&f64> = lon_vec.extend(lat_vec.iter()).collect();
//     // combined.extend(zeros.iter().cloned());
//     // let tmat = DMat::from_row_vec(3, zeros.len(), &combined);
//     let tmat = DMat::from_row_vec(3, 2, &test);
//     // build input vector of x, y, and z columns
//     // let inp = DMat::from_row_vec(3, 1, vec![lon_vec, lat_vec, h_vec]);
//     (vec![1.], vec![2.])
// }

/// Bounds checking for input values
pub fn check<T>(to_check: T, bounds: (T, T)) -> Result<T, ()>
    where T: std::cmp::PartialOrd + fmt::Display + Copy
{
    match to_check {
        to_check if bounds.0 <= to_check && to_check <= bounds.1 => Ok(to_check),
        _ => Err(()),
    }
}

/// Round Easting, Northing, and Orthometric height to the nearest millimetre
pub fn round_to_nearest_mm(x: f64, y: f64, z: f64) -> (f64, f64, f64) {
    let new_x = (x * 1000.).round() as f64 / 1000.;
    let new_y = (y * 1000.).round() as f64 / 1000.;
    let new_z = (z * 1000.).round() as f64 / 1000.;
    (new_x, new_y, new_z)
}

/// Round a float to nine decimal places
pub fn round_to_eight(x: f64, y: f64) -> (f64, f64) {
    let new_x = (x * 100000000.).round() as f64 / 100000000.;
    let new_y = (y * 100000000.).round() as f64 / 100000000.;
    (new_x, new_y)
}

/// Try to get OSTN02 shift parameters, and calculate offsets
pub fn get_ostn_ref(x: &i32, y: &i32) -> Result<(f64, f64, f64), ()> {
    // let key = format!("{:03x}{:03x}", y, x);
    // optimisation from https://github.com/hoodie/concatenation_benchmarks-rs
    let mut key = String::with_capacity(32);
    key.push_str(HEXKEYS.get(y).unwrap());
    key.push_str(HEXKEYS.get(x).unwrap());
    // Some or None, so convert to Result, which we can try!
    let result = try!(ostn02_lookup(&*key).ok_or(()));
    Ok((result.0 as f64 / 1000. + MIN_X_SHIFT,
        result.1 as f64 / 1000. + MIN_Y_SHIFT,
        result.2 as f64 / 1000. + MIN_Z_SHIFT))

}

// Input values must be valid ETRS89 grid references
// See p20 of the transformation user guide at
// https://www.ordnancesurvey.co.uk/business-and-government/help-and-support/navigation-technology/os-net/formats-for-developers.html
pub fn ostn02_shifts(x: &f64, y: &f64) -> Result<(f64, f64, f64), ()> {
    let e_index = (*x / 1000.) as i32;
    let n_index = (*y / 1000.) as i32;

    // eastings and northings of the south-west corner of the cell
    let x0 = e_index as i32 * 1000;
    let y0 = n_index as i32 * 1000;

    // The easting, northing and geoid shifts for the four corners of the cell
    // any of these could be Err, so use try!

    // bottom-left grid intersection
    let s0: (f64, f64, f64) = try!(get_ostn_ref(&(e_index), &(n_index)));
    // bottom-right
    let s1: (f64, f64, f64) = try!(get_ostn_ref(&(e_index + 1), &(n_index + 0)));
    // top-left
    let s2: (f64, f64, f64) = try!(get_ostn_ref(&(e_index + 0), &(n_index + 1)));
    // top-right
    let s3: (f64, f64, f64) = try!(get_ostn_ref(&(e_index + 1), &(n_index + 1)));

    // offset within square
    let dx = x - (x0 as f64);
    let dy = y - (y0 as f64);

    let t = dx / 1000.;
    let u = dy / 1000.;

    let f0 = (1. - t as f64) * (1. - u as f64);
    let f1 = t as f64 * (1. - u as f64);
    let f2 = (1. - t as f64) * u as f64;
    let f3 = t as f64 * u as f64;

    // bilinear interpolation, to obtain the actual shifts
    let se = f0 * s0.0 + f1 * s1.0 + f2 * s2.0 + f3 * s3.0;
    let sn = f0 * s0.1 + f1 * s1.1 + f2 * s2.1 + f3 * s3.1;
    let sg = f0 * s0.2 + f1 * s1.2 + f2 * s2.2 + f3 * s3.2;

    Ok(round_to_nearest_mm(se, sn, sg))

}

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

    #[test]
    // original coordinates are 651307.003, 313255.686
    fn test_ostn_hashmap_retrieval() {
        let eastings = 651;
        let northings = 313;
        let expected = (102.775, -78.244, 44.252);
        assert_eq!(expected, get_ostn_ref(&eastings, &northings).unwrap());
    }

    #[test]
    #[should_panic]
    fn test_failed_ostn_hashmap_retrieval() {
        // we're try!ing this in the shift calculation function, so an Err is fine
        let eastings = 999;
        let northings = 999;
        let expected = (1., 1., 1.);
        assert_eq!(expected, get_ostn_ref(&eastings, &northings).unwrap());
    }

    #[test]
    fn test_ostn02_shift_incorporation() {
        // these are the input values and corrections on p20-21
        let eastings = 651307.003;
        let northings = 313255.686;
        let expected = (102.789, -78.238, 44.244);
        assert_eq!(expected, ostn02_shifts(&eastings, &northings).unwrap());
    }

    #[test]
    #[should_panic]
    fn test_min_lon_extents() {
        let max_lon = 1.768960;
        let min_lon = -6.379880;
        // below min_lon
        check(&-6.379881, (&min_lon, &max_lon)).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_min_lat_extents() {
        let max_lat = 55.811741;
        let min_lat = 49.871159;
        // below min lat
        check(&49.871158, (&min_lat, &max_lat)).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_max_lon_extents() {
        let max_lon = 1.768960;
        let min_lon = -6.379880;
        // above max lon
        check(&1.768961, (&min_lon, &max_lon)).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_max_lat_extents() {
        let max_lat = 55.811741;
        let min_lat = 49.871159;
        // above max lat
        check(&55.811742, (&min_lat, &max_lat)).unwrap();
    }
}
<|endoftext|>


<commit_before>#![allow(unknown_lints)]
#![allow(float_cmp)]

use std::mem::transmute;
use rustc::ty::layout::TargetDataLayout;

use error::{EvalError, EvalResult};
use memory::{Memory, MemoryPointer};

pub(super) fn bytes_to_f32(bytes: u128) -> f32 {
    unsafe { transmute::<u32, f32>(bytes as u32) }
}

pub(super) fn bytes_to_f64(bytes: u128) -> f64 {
    unsafe { transmute::<u64, f64>(bytes as u64) }
}

pub(super) fn f32_to_bytes(f: f32) -> u128 {
    unsafe { transmute::<f32, u32>(f) as u128 }
}

pub(super) fn f64_to_bytes(f: f64) -> u128 {
    unsafe { transmute::<f64, u64>(f) as u128 }
}

/// A `Value` represents a single self-contained Rust value.
///
/// A `Value` can either refer to a block of memory inside an allocation (`ByRef`) or to a primitve
/// value held directly, outside of any allocation (`ByVal`).
///
/// For optimization of a few very common cases, there is also a representation for a pair of
/// primitive values (`ByValPair`). It allows Miri to avoid making allocations for checked binary
/// operations and fat pointers. This idea was taken from rustc's trans.
#[derive(Clone, Copy, Debug)]
pub enum Value {
    ByRef(Pointer),
    ByVal(PrimVal),
    ByValPair(PrimVal, PrimVal),
}

/// A wrapper type around `PrimVal` that cannot be turned back into a `PrimVal` accidentally.
/// This type clears up a few APIs where having a `PrimVal` argument for something that is
/// potentially an integer pointer or a pointer to an allocation was unclear.
#[derive(Clone, Copy, Debug)]
pub struct Pointer {
    primval: PrimVal,
}

impl<'tcx> Pointer {
    pub fn null() -> Self {
        PrimVal::Bytes(0).into()
    }
    pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
        self.primval.to_ptr()
    }
    pub fn into_inner_primval(self) -> PrimVal {
        self.primval
    }

    pub(crate) fn signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        self.primval.signed_offset(i, layout).map(Pointer::from)
    }

    pub(crate) fn offset(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        self.primval.offset(i, layout).map(Pointer::from)
    }

    pub(crate) fn wrapping_signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        self.primval.wrapping_signed_offset(i, layout).map(Pointer::from)
    }

    pub fn is_null(self) -> EvalResult<'tcx, bool> {
        match self.primval {
            PrimVal::Bytes(b) => Ok(b == 0),
            PrimVal::Ptr(_) => Ok(false),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub fn with_extra(self, extra: PrimVal) -> Value {
        Value::ByValPair(self.primval, extra)
    }
    pub fn to_value(self) -> Value {
        Value::ByVal(self.primval)
    }
}

impl ::std::convert::From<PrimVal> for Pointer {
    fn from(primval: PrimVal) -> Self {
        Pointer { primval }
    }
}

impl ::std::convert::From<MemoryPointer> for Pointer {
    fn from(ptr: MemoryPointer) -> Self {
        PrimVal::Ptr(ptr).into()
    }
}

/// A `PrimVal` represents an immediate, primitive value existing outside of a
/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
/// size. Like a range of bytes in an `Allocation`, a `PrimVal` can either represent the raw bytes
/// of a simple value, a pointer into another `Allocation`, or be undefined.
#[derive(Clone, Copy, Debug)]
pub enum PrimVal {
    /// The raw bytes of a simple value.
    Bytes(u128),

    /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
    /// relocations, but a `PrimVal` is only large enough to contain one, so we just represent the
    /// relocation and its associated offset together as a `MemoryPointer` here.
    Ptr(MemoryPointer),

    /// An undefined `PrimVal`, for representing values that aren't safe to examine, but are safe
    /// to copy around, just like undefined bytes in an `Allocation`.
    Undef,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PrimValKind {
    I8, I16, I32, I64, I128,
    U8, U16, U32, U64, U128,
    F32, F64,
    Bool,
    Char,
    Ptr,
    FnPtr,
}

impl<'a, 'tcx: 'a> Value {
    pub(super) fn read_ptr(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, Pointer> {
        use self::Value::*;
        match *self {
            ByRef(ptr) => mem.read_ptr(ptr.to_ptr()?),
            ByVal(ptr) | ByValPair(ptr, _) => Ok(ptr.into()),
        }
    }

    pub(super) fn expect_ptr_vtable_pair(
        &self,
        mem: &Memory<'a, 'tcx>
    ) -> EvalResult<'tcx, (Pointer, MemoryPointer)> {
        use self::Value::*;
        match *self {
            ByRef(ref_ptr) => {
                let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
                let vtable = mem.read_ptr(ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?)?;
                Ok((ptr, vtable.to_ptr()?))
            }

            ByValPair(ptr, vtable) => Ok((ptr.into(), vtable.to_ptr()?)),

            _ => bug!("expected ptr and vtable, got {:?}", self),
        }
    }

    pub(super) fn expect_slice(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, (Pointer, u64)> {
        use self::Value::*;
        match *self {
            ByRef(ref_ptr) => {
                let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
                let len = mem.read_usize(ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?)?;
                Ok((ptr, len))
            },
            ByValPair(ptr, val) => {
                let len = val.to_u128()?;
                assert_eq!(len as u64 as u128, len);
                Ok((ptr.into(), len as u64))
            },
            ByVal(_) => unimplemented!(),
        }
    }
}

impl<'tcx> PrimVal {
    pub fn from_u128(n: u128) -> Self {
        PrimVal::Bytes(n)
    }

    pub fn from_i128(n: i128) -> Self {
        PrimVal::Bytes(n as u128)
    }

    pub fn from_f32(f: f32) -> Self {
        PrimVal::Bytes(f32_to_bytes(f))
    }

    pub fn from_f64(f: f64) -> Self {
        PrimVal::Bytes(f64_to_bytes(f))
    }

    pub fn from_bool(b: bool) -> Self {
        PrimVal::Bytes(b as u128)
    }

    pub fn from_char(c: char) -> Self {
        PrimVal::Bytes(c as u128)
    }

    pub fn to_bytes(self) -> EvalResult<'tcx, u128> {
        match self {
            PrimVal::Bytes(b) => Ok(b),
            PrimVal::Ptr(_) => Err(EvalError::ReadPointerAsBytes),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
        match self {
            PrimVal::Bytes(_) => Err(EvalError::ReadBytesAsPointer),
            PrimVal::Ptr(p) => Ok(p),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub fn is_bytes(self) -> bool {
        match self {
            PrimVal::Bytes(_) => true,
            _ => false,
        }
    }

    pub fn is_ptr(self) -> bool {
        match self {
            PrimVal::Ptr(_) => true,
            _ => false,
        }
    }

    pub fn is_undef(self) -> bool {
        match self {
            PrimVal::Undef => true,
            _ => false,
        }
    }

    pub fn to_u128(self) -> EvalResult<'tcx, u128> {
        self.to_bytes()
    }

    pub fn to_u64(self) -> EvalResult<'tcx, u64> {
        self.to_bytes().map(|b| {
            assert_eq!(b as u64 as u128, b);
            b as u64
        })
    }

    pub fn to_i32(self) -> EvalResult<'tcx, i32> {
        self.to_bytes().map(|b| {
            assert_eq!(b as i32 as u128, b);
            b as i32
        })
    }

    pub fn to_i128(self) -> EvalResult<'tcx, i128> {
        self.to_bytes().map(|b| b as i128)
    }

    pub fn to_i64(self) -> EvalResult<'tcx, i64> {
        self.to_bytes().map(|b| {
            assert_eq!(b as i64 as u128, b);
            b as i64
        })
    }

    pub fn to_f32(self) -> EvalResult<'tcx, f32> {
        self.to_bytes().map(bytes_to_f32)
    }

    pub fn to_f64(self) -> EvalResult<'tcx, f64> {
        self.to_bytes().map(bytes_to_f64)
    }

    pub fn to_bool(self) -> EvalResult<'tcx, bool> {
        match self.to_bytes()? {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(EvalError::InvalidBool),
        }
    }

    pub(crate) fn signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        match self {
            PrimVal::Bytes(b) => {
                assert_eq!(b as u64 as u128, b);
                Ok(PrimVal::Bytes(signed_offset(b as u64, i, layout)? as u128))
            },
            PrimVal::Ptr(ptr) => ptr.signed_offset(i, layout).map(PrimVal::Ptr),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub(crate) fn offset(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        match self {
            PrimVal::Bytes(b) => {
                assert_eq!(b as u64 as u128, b);
                Ok(PrimVal::Bytes(offset(b as u64, i, layout)? as u128))
            },
            PrimVal::Ptr(ptr) => ptr.offset(i, layout).map(PrimVal::Ptr),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub(crate) fn wrapping_signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        match self {
            PrimVal::Bytes(b) => {
                assert_eq!(b as u64 as u128, b);
                Ok(PrimVal::Bytes(wrapping_signed_offset(b as u64, i, layout) as u128))
            },
            PrimVal::Ptr(ptr) => Ok(PrimVal::Ptr(ptr.wrapping_signed_offset(i, layout))),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }
}

// Overflow checking only works properly on the range from -u64 to +u64.
pub fn overflowing_signed_offset<'tcx>(val: u64, i: i128, layout: &TargetDataLayout) -> (u64, bool) {
    // FIXME: is it possible to over/underflow here?
    if i < 0 {
        // trickery to ensure that i64::min_value() works fine
        // this formula only works for true negative values, it panics for zero!
        let n = u64::max_value() - (i as u64) + 1;
        val.overflowing_sub(n)
    } else {
        overflowing_offset(val, i as u64, layout)
    }
}

pub fn overflowing_offset<'tcx>(val: u64, i: u64, layout: &TargetDataLayout) -> (u64, bool) {
    let (res, over) = val.overflowing_add(i);
    ((res as u128 % (1u128 << layout.pointer_size.bits())) as u64,
     over || res as u128 >= (1u128 << layout.pointer_size.bits()))
}

pub fn signed_offset<'tcx>(val: u64, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, u64> {
    let (res, over) = overflowing_signed_offset(val, i as i128, layout);
    if over {
        Err(EvalError::OverflowingMath)
    } else {
        Ok(res)
    }
}

pub fn offset<'tcx>(val: u64, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, u64> {
    let (res, over) = overflowing_offset(val, i, layout);
    if over {
        Err(EvalError::OverflowingMath)
    } else {
        Ok(res)
    }
}

pub fn wrapping_signed_offset<'tcx>(val: u64, i: i64, layout: &TargetDataLayout) -> u64 {
    overflowing_signed_offset(val, i as i128, layout).0
}

impl PrimValKind {
    pub fn is_int(self) -> bool {
        use self::PrimValKind::*;
        match self {
            I8 | I16 | I32 | I64 | I128 | U8 | U16 | U32 | U64 | U128 => true,
            _ => false,
        }
    }

    pub fn is_signed_int(self) -> bool {
        use self::PrimValKind::*;
        match self {
            I8 | I16 | I32 | I64 | I128 => true,
            _ => false,
        }
    }

     pub fn is_float(self) -> bool {
        use self::PrimValKind::*;
        match self {
            F32 | F64 => true,
            _ => false,
        }
    }

    pub fn from_uint_size(size: u64) -> Self {
        match size {
            1 => PrimValKind::U8,
            2 => PrimValKind::U16,
            4 => PrimValKind::U32,
            8 => PrimValKind::U64,
            16 => PrimValKind::U128,
            _ => bug!("can't make uint with size {}", size),
        }
    }

    pub fn from_int_size(size: u64) -> Self {
        match size {
            1 => PrimValKind::I8,
            2 => PrimValKind::I16,
            4 => PrimValKind::I32,
            8 => PrimValKind::I64,
            16 => PrimValKind::I128,
            _ => bug!("can't make int with size {}", size),
        }
    }

    pub fn is_ptr(self) -> bool {
        use self::PrimValKind::*;
        match self {
            Ptr | FnPtr => true,
            _ => false,
        }
    }
}
<commit_msg>Remove `*offset*` methods from `PrimVal` onto `Pointer`<commit_after>#![allow(unknown_lints)]
#![allow(float_cmp)]

use std::mem::transmute;
use rustc::ty::layout::TargetDataLayout;

use error::{EvalError, EvalResult};
use memory::{Memory, MemoryPointer};

pub(super) fn bytes_to_f32(bytes: u128) -> f32 {
    unsafe { transmute::<u32, f32>(bytes as u32) }
}

pub(super) fn bytes_to_f64(bytes: u128) -> f64 {
    unsafe { transmute::<u64, f64>(bytes as u64) }
}

pub(super) fn f32_to_bytes(f: f32) -> u128 {
    unsafe { transmute::<f32, u32>(f) as u128 }
}

pub(super) fn f64_to_bytes(f: f64) -> u128 {
    unsafe { transmute::<f64, u64>(f) as u128 }
}

/// A `Value` represents a single self-contained Rust value.
///
/// A `Value` can either refer to a block of memory inside an allocation (`ByRef`) or to a primitve
/// value held directly, outside of any allocation (`ByVal`).
///
/// For optimization of a few very common cases, there is also a representation for a pair of
/// primitive values (`ByValPair`). It allows Miri to avoid making allocations for checked binary
/// operations and fat pointers. This idea was taken from rustc's trans.
#[derive(Clone, Copy, Debug)]
pub enum Value {
    ByRef(Pointer),
    ByVal(PrimVal),
    ByValPair(PrimVal, PrimVal),
}

/// A wrapper type around `PrimVal` that cannot be turned back into a `PrimVal` accidentally.
/// This type clears up a few APIs where having a `PrimVal` argument for something that is
/// potentially an integer pointer or a pointer to an allocation was unclear.
#[derive(Clone, Copy, Debug)]
pub struct Pointer {
    primval: PrimVal,
}

impl<'tcx> Pointer {
    pub fn null() -> Self {
        PrimVal::Bytes(0).into()
    }
    pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
        self.primval.to_ptr()
    }
    pub fn into_inner_primval(self) -> PrimVal {
        self.primval
    }

    pub(crate) fn signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        match self.primval {
            PrimVal::Bytes(b) => {
                assert_eq!(b as u64 as u128, b);
                Ok(Pointer::from(PrimVal::Bytes(signed_offset(b as u64, i, layout)? as u128)))
            },
            PrimVal::Ptr(ptr) => ptr.signed_offset(i, layout).map(Pointer::from),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub(crate) fn offset(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        match self.primval {
            PrimVal::Bytes(b) => {
                assert_eq!(b as u64 as u128, b);
                Ok(Pointer::from(PrimVal::Bytes(offset(b as u64, i, layout)? as u128)))
            },
            PrimVal::Ptr(ptr) => ptr.offset(i, layout).map(Pointer::from),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub(crate) fn wrapping_signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
        match self.primval {
            PrimVal::Bytes(b) => {
                assert_eq!(b as u64 as u128, b);
                Ok(Pointer::from(PrimVal::Bytes(wrapping_signed_offset(b as u64, i, layout) as u128)))
            },
            PrimVal::Ptr(ptr) => Ok(Pointer::from(ptr.wrapping_signed_offset(i, layout))),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub fn is_null(self) -> EvalResult<'tcx, bool> {
        match self.primval {
            PrimVal::Bytes(b) => Ok(b == 0),
            PrimVal::Ptr(_) => Ok(false),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub fn with_extra(self, extra: PrimVal) -> Value {
        Value::ByValPair(self.primval, extra)
    }
    pub fn to_value(self) -> Value {
        Value::ByVal(self.primval)
    }
}

impl ::std::convert::From<PrimVal> for Pointer {
    fn from(primval: PrimVal) -> Self {
        Pointer { primval }
    }
}

impl ::std::convert::From<MemoryPointer> for Pointer {
    fn from(ptr: MemoryPointer) -> Self {
        PrimVal::Ptr(ptr).into()
    }
}

/// A `PrimVal` represents an immediate, primitive value existing outside of a
/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
/// size. Like a range of bytes in an `Allocation`, a `PrimVal` can either represent the raw bytes
/// of a simple value, a pointer into another `Allocation`, or be undefined.
#[derive(Clone, Copy, Debug)]
pub enum PrimVal {
    /// The raw bytes of a simple value.
    Bytes(u128),

    /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
    /// relocations, but a `PrimVal` is only large enough to contain one, so we just represent the
    /// relocation and its associated offset together as a `MemoryPointer` here.
    Ptr(MemoryPointer),

    /// An undefined `PrimVal`, for representing values that aren't safe to examine, but are safe
    /// to copy around, just like undefined bytes in an `Allocation`.
    Undef,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PrimValKind {
    I8, I16, I32, I64, I128,
    U8, U16, U32, U64, U128,
    F32, F64,
    Bool,
    Char,
    Ptr,
    FnPtr,
}

impl<'a, 'tcx: 'a> Value {
    pub(super) fn read_ptr(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, Pointer> {
        use self::Value::*;
        match *self {
            ByRef(ptr) => mem.read_ptr(ptr.to_ptr()?),
            ByVal(ptr) | ByValPair(ptr, _) => Ok(ptr.into()),
        }
    }

    pub(super) fn expect_ptr_vtable_pair(
        &self,
        mem: &Memory<'a, 'tcx>
    ) -> EvalResult<'tcx, (Pointer, MemoryPointer)> {
        use self::Value::*;
        match *self {
            ByRef(ref_ptr) => {
                let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
                let vtable = mem.read_ptr(ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?)?;
                Ok((ptr, vtable.to_ptr()?))
            }

            ByValPair(ptr, vtable) => Ok((ptr.into(), vtable.to_ptr()?)),

            _ => bug!("expected ptr and vtable, got {:?}", self),
        }
    }

    pub(super) fn expect_slice(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, (Pointer, u64)> {
        use self::Value::*;
        match *self {
            ByRef(ref_ptr) => {
                let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
                let len = mem.read_usize(ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?)?;
                Ok((ptr, len))
            },
            ByValPair(ptr, val) => {
                let len = val.to_u128()?;
                assert_eq!(len as u64 as u128, len);
                Ok((ptr.into(), len as u64))
            },
            ByVal(_) => unimplemented!(),
        }
    }
}

impl<'tcx> PrimVal {
    pub fn from_u128(n: u128) -> Self {
        PrimVal::Bytes(n)
    }

    pub fn from_i128(n: i128) -> Self {
        PrimVal::Bytes(n as u128)
    }

    pub fn from_f32(f: f32) -> Self {
        PrimVal::Bytes(f32_to_bytes(f))
    }

    pub fn from_f64(f: f64) -> Self {
        PrimVal::Bytes(f64_to_bytes(f))
    }

    pub fn from_bool(b: bool) -> Self {
        PrimVal::Bytes(b as u128)
    }

    pub fn from_char(c: char) -> Self {
        PrimVal::Bytes(c as u128)
    }

    pub fn to_bytes(self) -> EvalResult<'tcx, u128> {
        match self {
            PrimVal::Bytes(b) => Ok(b),
            PrimVal::Ptr(_) => Err(EvalError::ReadPointerAsBytes),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
        match self {
            PrimVal::Bytes(_) => Err(EvalError::ReadBytesAsPointer),
            PrimVal::Ptr(p) => Ok(p),
            PrimVal::Undef => Err(EvalError::ReadUndefBytes),
        }
    }

    pub fn is_bytes(self) -> bool {
        match self {
            PrimVal::Bytes(_) => true,
            _ => false,
        }
    }

    pub fn is_ptr(self) -> bool {
        match self {
            PrimVal::Ptr(_) => true,
            _ => false,
        }
    }

    pub fn is_undef(self) -> bool {
        match self {
            PrimVal::Undef => true,
            _ => false,
        }
    }

    pub fn to_u128(self) -> EvalResult<'tcx, u128> {
        self.to_bytes()
    }

    pub fn to_u64(self) -> EvalResult<'tcx, u64> {
        self.to_bytes().map(|b| {
            assert_eq!(b as u64 as u128, b);
            b as u64
        })
    }

    pub fn to_i32(self) -> EvalResult<'tcx, i32> {
        self.to_bytes().map(|b| {
            assert_eq!(b as i32 as u128, b);
            b as i32
        })
    }

    pub fn to_i128(self) -> EvalResult<'tcx, i128> {
        self.to_bytes().map(|b| b as i128)
    }

    pub fn to_i64(self) -> EvalResult<'tcx, i64> {
        self.to_bytes().map(|b| {
            assert_eq!(b as i64 as u128, b);
            b as i64
        })
    }

    pub fn to_f32(self) -> EvalResult<'tcx, f32> {
        self.to_bytes().map(bytes_to_f32)
    }

    pub fn to_f64(self) -> EvalResult<'tcx, f64> {
        self.to_bytes().map(bytes_to_f64)
    }

    pub fn to_bool(self) -> EvalResult<'tcx, bool> {
        match self.to_bytes()? {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(EvalError::InvalidBool),
        }
    }
}

// Overflow checking only works properly on the range from -u64 to +u64.
pub fn overflowing_signed_offset<'tcx>(val: u64, i: i128, layout: &TargetDataLayout) -> (u64, bool) {
    // FIXME: is it possible to over/underflow here?
    if i < 0 {
        // trickery to ensure that i64::min_value() works fine
        // this formula only works for true negative values, it panics for zero!
        let n = u64::max_value() - (i as u64) + 1;
        val.overflowing_sub(n)
    } else {
        overflowing_offset(val, i as u64, layout)
    }
}

pub fn overflowing_offset<'tcx>(val: u64, i: u64, layout: &TargetDataLayout) -> (u64, bool) {
    let (res, over) = val.overflowing_add(i);
    ((res as u128 % (1u128 << layout.pointer_size.bits())) as u64,
     over || res as u128 >= (1u128 << layout.pointer_size.bits()))
}

pub fn signed_offset<'tcx>(val: u64, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, u64> {
    let (res, over) = overflowing_signed_offset(val, i as i128, layout);
    if over {
        Err(EvalError::OverflowingMath)
    } else {
        Ok(res)
    }
}

pub fn offset<'tcx>(val: u64, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, u64> {
    let (res, over) = overflowing_offset(val, i, layout);
    if over {
        Err(EvalError::OverflowingMath)
    } else {
        Ok(res)
    }
}

pub fn wrapping_signed_offset<'tcx>(val: u64, i: i64, layout: &TargetDataLayout) -> u64 {
    overflowing_signed_offset(val, i as i128, layout).0
}

impl PrimValKind {
    pub fn is_int(self) -> bool {
        use self::PrimValKind::*;
        match self {
            I8 | I16 | I32 | I64 | I128 | U8 | U16 | U32 | U64 | U128 => true,
            _ => false,
        }
    }

    pub fn is_signed_int(self) -> bool {
        use self::PrimValKind::*;
        match self {
            I8 | I16 | I32 | I64 | I128 => true,
            _ => false,
        }
    }

     pub fn is_float(self) -> bool {
        use self::PrimValKind::*;
        match self {
            F32 | F64 => true,
            _ => false,
        }
    }

    pub fn from_uint_size(size: u64) -> Self {
        match size {
            1 => PrimValKind::U8,
            2 => PrimValKind::U16,
            4 => PrimValKind::U32,
            8 => PrimValKind::U64,
            16 => PrimValKind::U128,
            _ => bug!("can't make uint with size {}", size),
        }
    }

    pub fn from_int_size(size: u64) -> Self {
        match size {
            1 => PrimValKind::I8,
            2 => PrimValKind::I16,
            4 => PrimValKind::I32,
            8 => PrimValKind::I64,
            16 => PrimValKind::I128,
            _ => bug!("can't make int with size {}", size),
        }
    }

    pub fn is_ptr(self) -> bool {
        use self::PrimValKind::*;
        match self {
            Ptr | FnPtr => true,
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>use crate::io::DecodeError;

pub enum VisitError<E> {
    LazyDecode(DecodeError),
    Custom(E),
}

impl<E: std::fmt::Display> std::fmt::Display for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::fmt::Debug> std::fmt::Debug for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::error::Error> std::error::Error for VisitError<E> {}

#[cfg(feature = "nightly")]
pub type NeverError = !;

#[cfg(not(feature = "nightly"))]
pub enum NeverError {}

impl From<VisitError<NeverError>> for DecodeError {
    fn from(err: VisitError<NeverError>) -> Self {
        match err {
            VisitError::Custom(err) => match err {},
            VisitError::LazyDecode(err) => err,
        }
    }
}

pub trait VisitResult {
    type Error;

    fn as_result(self) -> Result<(), Self::Error>;
}

impl VisitResult for () {
    type Error = NeverError;

    fn as_result(self) -> Result<(), Self::Error> {
        Ok(())
    }
}

impl VisitResult for bool {
    type Error = ();

    fn as_result(self) -> Result<(), Self::Error> {
        match self {
            true => Ok(()),
            false => Err(()),
        }
    }
}

impl<E> VisitResult for Result<(), E> {
    type Error = E;

    fn as_result(self) -> Result<(), Self::Error> {
        self
    }
}

pub use wasmbin_derive::WasmbinVisit;
pub trait WasmbinVisit: 'static + Sized {
    fn visit<'a, T: 'static, R: VisitResult, F: FnMut(&'a T) -> R>(
        &'a self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child(&mut move |item| f(item).as_result())
    }

    fn visit_mut<'a, T: 'static, R: VisitResult, F: FnMut(&'a mut T) -> R>(
        &'a mut self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child_mut(&mut move |item| f(item).as_result())
    }

    fn visit_child<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        match std::any::Any::downcast_ref(self) {
            Some(v) => f(v).map_err(VisitError::Custom),
            None => self.visit_children(f),
        }
    }

    fn visit_child_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        match std::any::Any::downcast_mut(self) {
            Some(v) => f(unsafe {
                // Working around an apparent bug in NLL: https://github.com/rust-lang/rust/issues/70255
                &mut *(v as *mut _)
            })
            .map_err(VisitError::Custom),
            None => self.visit_children_mut(f),
        }
    }

    fn visit_children<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }

    fn visit_children_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }
}
<commit_msg>Allow recursive visiting<commit_after>use crate::io::DecodeError;

pub enum VisitError<E> {
    LazyDecode(DecodeError),
    Custom(E),
}

impl<E: std::fmt::Display> std::fmt::Display for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::fmt::Debug> std::fmt::Debug for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::error::Error> std::error::Error for VisitError<E> {}

#[cfg(feature = "nightly")]
pub type NeverError = !;

#[cfg(not(feature = "nightly"))]
pub enum NeverError {}

impl From<VisitError<NeverError>> for DecodeError {
    fn from(err: VisitError<NeverError>) -> Self {
        match err {
            VisitError::Custom(err) => match err {},
            VisitError::LazyDecode(err) => err,
        }
    }
}

pub trait VisitResult {
    type Error;

    fn as_result(self) -> Result<(), Self::Error>;
}

impl VisitResult for () {
    type Error = NeverError;

    fn as_result(self) -> Result<(), Self::Error> {
        Ok(())
    }
}

impl VisitResult for bool {
    type Error = ();

    fn as_result(self) -> Result<(), Self::Error> {
        match self {
            true => Ok(()),
            false => Err(()),
        }
    }
}

impl<E> VisitResult for Result<(), E> {
    type Error = E;

    fn as_result(self) -> Result<(), Self::Error> {
        self
    }
}

pub use wasmbin_derive::WasmbinVisit;
pub trait WasmbinVisit: 'static + Sized {
    fn visit<'a, T: 'static, R: VisitResult, F: FnMut(&'a T) -> R>(
        &'a self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child(&mut move |item| f(item).as_result())
    }

    fn visit_mut<'a, T: 'static, R: VisitResult, F: FnMut(&'a mut T) -> R>(
        &'a mut self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child_mut(&mut move |item| f(item).as_result())
    }

    fn visit_child<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        if let Some(v) = std::any::Any::downcast_ref(self) {
            f(v).map_err(VisitError::Custom)?;
        }
        self.visit_children(f)
    }

    fn visit_child_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        if let Some(v) = std::any::Any::downcast_mut(self) {
            f(unsafe {
                // Working around an apparent bug in NLL: https://github.com/rust-lang/rust/issues/70255
                &mut *(v as *mut _)
            }).map_err(VisitError::Custom)?;
        }
        self.visit_children_mut(f)
    }

    fn visit_children<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }

    fn visit_children_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>pub use telegram_bot_raw::{Integer, Float, True, Request};
pub use telegram_bot_raw::{Update, UpdateKind, RawUpdate};
pub use telegram_bot_raw::{User, Group, Supergroup, Channel, Chat, RawChat};
pub use telegram_bot_raw::{Message, MessageKind, RawMessage, Forward, ForwardFrom};
pub use telegram_bot_raw::{MessageEntity, MessageEntityKind, RawMessageEntity};
pub use telegram_bot_raw::{Audio, Document, PhotoSize, Sticker, Video, Voice};
pub use telegram_bot_raw::{Contact, Location, Venue};

pub use telegram_bot_raw::{ParseMode, ChatId, MessageId};
pub use telegram_bot_raw::{ReplyMarkup, InlineKeyboardMarkup, ReplyKeyboardMarkup};
pub use telegram_bot_raw::{ReplyKeyboardRemove, ForceReply};
pub use telegram_bot_raw::{GetMe, ForwardMessage, SendLocation, SendMessage};
pub use telegram_bot_raw::{ChatAction, SendChatAction};
<commit_msg>refactor: reexport types from -raw<commit_after>pub use telegram_bot_raw::{Integer, Float, True, Request};
pub use telegram_bot_raw::{Update, UpdateKind, RawUpdate};
pub use telegram_bot_raw::{User, Group, Supergroup, Channel, Chat, RawChat};
pub use telegram_bot_raw::{Message, MessageKind, RawMessage, Forward, ForwardFrom};
pub use telegram_bot_raw::{MessageEntity, MessageEntityKind, RawMessageEntity};
pub use telegram_bot_raw::{Audio, Document, PhotoSize, Sticker, Video, Voice};
pub use telegram_bot_raw::{Contact, Location, Venue};

pub use telegram_bot_raw::{ParseMode, ChatId, UserId, MessageId};
pub use telegram_bot_raw::{ReplyMarkup, InlineKeyboardMarkup, ReplyKeyboardMarkup};
pub use telegram_bot_raw::{ReplyKeyboardRemove, ForceReply};
pub use telegram_bot_raw::{GetMe, GetUpdates, ForwardMessage, SendLocation, SendMessage};
pub use telegram_bot_raw::{GetChat, LeaveChat};
pub use telegram_bot_raw::{ChatAction, SendChatAction};
pub use telegram_bot_raw::{GetChatAdministrators, GetChatMember, GetChatMembersCount};
pub use telegram_bot_raw::{KickChatMember, UnbanChatMember};
<|endoftext|>


<commit_before>extern crate image;

use image::*;
use std::path::Path;
use super::algorithm::Bin;

pub fn draw_bin(path: &AsRef<Path>, images: &[RgbaImage], bin: &Bin) -> u64 {
  let mut atlas = RgbaImage::new(bin.size.w, bin.size.h);
  for p in &bin.placements {
    let img: ImageBuffer<_, _> = if p.rect.flipped {
      imageops::rotate270(&images[p.index as usize])
    } else {
      images[p.index as usize].to_owned()
    };
    image::imageops::replace(&mut atlas, &img, p.rect.x, p.rect.y);
  }
  atlas.save(path).unwrap();
  path.as_ref().metadata().unwrap().len()
}
<commit_msg>removed redundant image cloning<commit_after>extern crate image;

use image::RgbaImage;
use image::imageops::{rotate270, replace as draw_img};
use std::path::Path;
use super::algorithm::Bin;

pub fn draw_bin(path: &AsRef<Path>, images: &[RgbaImage], bin: &Bin) -> u64 {
  let mut atlas = RgbaImage::new(bin.size.w, bin.size.h);
  for p in &bin.placements {
    if p.rect.flipped {
      draw_img(&mut atlas, &rotate270(&images[p.index as usize]), p.rect.x, p.rect.y);
    } else {
      draw_img(&mut atlas, &images[p.index as usize], p.rect.x, p.rect.y);
    };
  }
  atlas.save(path).expect(format!("Failed to save atlas {:?}", path.as_ref()).as_ref());
  path.as_ref().metadata().unwrap().len()
}
<|endoftext|>