<commit_before>use super::{Connection, Message, MessageItem, Error};
use std::collections::BTreeMap;

/// Client side properties - get and set properties on a remote application.
pub struct Props<'a> {
    name: String,
    path: String,
    interface: String,
    timeout_ms: i32,
    conn: &'a Connection,
}

impl<'a> Props<'a> {
    pub fn new(conn: &'a Connection, name: &str, path: &str, interface: &str, timeout_ms: i32) -> Props<'a> {
        Props {
            name: name.to_string(),
            path: path.to_string(),
            interface: interface.to_string(),
            timeout_ms: timeout_ms,
            conn: conn,
        }
    }

    pub fn get(&self, propname: &str) -> Result<MessageItem, Error> {
        let mut m = Message::new_method_call(&self.name, &self.path,
            "org.freedesktop.DBus.Properties", "Get").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string())
        ]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Variant(ref v) = &reply[0] {
                return Ok((**v).clone())
            }
       }
       let f = format!("Invalid reply for property get {}: '{:?}'", propname, reply);
       return Err(Error::new_custom("InvalidReply", &f));
    }

    pub fn set(&self, propname: &str, value: MessageItem) -> Result<(), Error> {
        let mut m = Message::new_method_call(&self.name, &self.path,
            "org.freedesktop.DBus.Properties", "Set").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string()),
            MessageItem::Variant(Box::new(value)),
        ]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        try!(r.as_result());
        Ok(())
    }

    pub fn get_all(&self) -> Result<BTreeMap<String, MessageItem>, Error> {
        let mut m = Message::new_method_call(&self.name, &self.path,
            "org.freedesktop.DBus.Properties", "GetAll").unwrap();
        m.append_items(&[MessageItem::Str(self.interface.clone())]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Array(ref a, _) = &reply[0] {
                let mut t = BTreeMap::new();
                let mut haserr = false;
                for p in a.iter() {
                    if let &MessageItem::DictEntry(ref k, ref v) = p {
                        if let &MessageItem::Str(ref ks) = &**k {
                            if let &MessageItem::Variant(ref vv) = &**v {
                                t.insert(ks.to_string(), (**vv).clone());
                            } else { haserr = true; };
                        } else { haserr = true; };
                    } else { haserr = true; };
                }
                if !haserr { return Ok(t) };
            }
        }
        let f = format!("Invalid reply for property GetAll: '{:?}'", reply);
        return Err(Error::new_custom("InvalidReply", &f));
    }
}

/// Wrapper around Props that keeps a map of fetched properties.
pub struct PropHandler<'a> {
    p: Props<'a>,
    map: BTreeMap<String, MessageItem>,
}

impl<'a> PropHandler<'a> {
    pub fn new(p: Props) -> PropHandler {
        PropHandler { p: p, map: BTreeMap::new() }
    }

    pub fn get_all(&mut self) -> Result<(), Error> {
        self.map = try!(self.p.get_all());
        Ok(())
    }

    pub fn map_mut(&mut self) -> &mut BTreeMap<String, MessageItem> { &mut self.map }
    pub fn map(&self) -> &BTreeMap<String, MessageItem> { &self.map }

    pub fn get(&mut self, propname: &str) -> Result<&MessageItem, Error> {
        let v = try!(self.p.get(propname));
        self.map.insert(propname.to_string(), v);
        Ok(self.map.get(propname).unwrap())
    }

    pub fn set(&mut self, propname: &str, value: MessageItem) -> Result<(), Error> {
        try!(self.p.set(propname, value.clone()));
        self.map.insert(propname.to_string(), value);
        Ok(())
    }

    fn invalid_args(m: &Message) -> Message {
        Message::new_error(m, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid arguments").unwrap()
    }

    /// Deprecated: use objpath instead
    fn handle_get(&self, msg: &mut Message) -> Message {
        let items = msg.get_items();
        let name = if let Some(s) = items.get(1) { s } else { return PropHandler::invalid_args(msg) };
        let name = if let &MessageItem::Str(ref s) = name { s } else { return PropHandler::invalid_args(msg) };
        let value = if let Some(s) = self.map.get(name) { s } else { return PropHandler::invalid_args(msg) };

        let mut reply = Message::new_method_return(msg).unwrap();
        reply.append_items(&[MessageItem::Variant(Box::new(value.clone()))]);
        reply
    }

    /// Deprecated: Broken. Use objpath instead
    fn handle_getall(&self, msg: &mut Message) -> Message {
        let mut reply = Message::new_method_return(msg).unwrap();
        for (k, v) in self.map.iter() {
            reply.append_items(&[MessageItem::DictEntry(Box::new(MessageItem::Str(k.clone())), Box::new(v.clone()))]);
        }
        reply
    }

    /// Deprecated: Broken. Use objpath instead
    /// Return value:
    ///   None => not handled,
    ///   Some(Err(())) => message reply send failed,
    ///   Some(Ok()) => message reply send ok
    pub fn handle_message(&mut self, msg: &mut Message) -> Option<Result<(), ()>> {
        let (_, path, iface, method) = msg.headers();
        if iface.is_none() || &*iface.unwrap() != "org.freedesktop.DBus.Properties" { return None; }
        if path.is_none() || path.unwrap() != self.p.path { return None; }
        if method.is_none() { return None; }

        let items = msg.get_items();
        if let Some(i) = items.get(0) {
            if let &MessageItem::Str(ref s) = i {
                if *s != self.p.interface { return None; }
            } else { return None; } // Hmm, invalid message
        } else { return None }; // Hmm, invalid message

        // Ok, we have a match
        let reply = match &*method.unwrap() {
            "Get" => self.handle_get(msg),
//            "Set" => self.handle_set(msg),
            "GetAll" => self.handle_getall(msg),
            _ => PropHandler::invalid_args(msg)
        };
        Some(self.p.conn.send(reply).map(|_| ()))
    }
}

/* Unfortunately org.freedesktop.DBus has no properties we can use for testing, but PolicyKit should be around on most distros. */
#[test]
fn test_get_policykit_version() {
    use super::BusType;
    let c = Connection::get_private(BusType::System).unwrap();
    let p = Props::new(&c, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority",
        "org.freedesktop.PolicyKit1.Authority", 10000);

    /* Let's use both the get and getall methods and see if we get the same result */
    let v = p.get("BackendVersion").unwrap();
    let vall = p.get_all().unwrap();
    let v2 = vall.get("BackendVersion").unwrap();

    assert_eq!(&v, &*v2);
    match v {
        MessageItem::Str(ref s) => { println!("Policykit Backend version is {}", s); }
        _ => { panic!("Invalid Get: {:?}", v); }
    };
}

<commit_msg>Remove deprecated functions<commit_after>use super::{Connection, Message, MessageItem, Error};
use std::collections::BTreeMap;

/// Client side properties - get and set properties on a remote application.
pub struct Props<'a> {
    name: String,
    path: String,
    interface: String,
    timeout_ms: i32,
    conn: &'a Connection,
}

impl<'a> Props<'a> {
    pub fn new(conn: &'a Connection, name: &str, path: &str, interface: &str, timeout_ms: i32) -> Props<'a> {
        Props {
            name: name.to_string(),
            path: path.to_string(),
            interface: interface.to_string(),
            timeout_ms: timeout_ms,
            conn: conn,
        }
    }

    pub fn get(&self, propname: &str) -> Result<MessageItem, Error> {
        let mut m = Message::new_method_call(&self.name, &self.path,
            "org.freedesktop.DBus.Properties", "Get").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string())
        ]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Variant(ref v) = &reply[0] {
                return Ok((**v).clone())
            }
       }
       let f = format!("Invalid reply for property get {}: '{:?}'", propname, reply);
       return Err(Error::new_custom("InvalidReply", &f));
    }

    pub fn set(&self, propname: &str, value: MessageItem) -> Result<(), Error> {
        let mut m = Message::new_method_call(&self.name, &self.path,
            "org.freedesktop.DBus.Properties", "Set").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string()),
            MessageItem::Variant(Box::new(value)),
        ]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        try!(r.as_result());
        Ok(())
    }

    pub fn get_all(&self) -> Result<BTreeMap<String, MessageItem>, Error> {
        let mut m = Message::new_method_call(&self.name, &self.path,
            "org.freedesktop.DBus.Properties", "GetAll").unwrap();
        m.append_items(&[MessageItem::Str(self.interface.clone())]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Array(ref a, _) = &reply[0] {
                let mut t = BTreeMap::new();
                let mut haserr = false;
                for p in a.iter() {
                    if let &MessageItem::DictEntry(ref k, ref v) = p {
                        if let &MessageItem::Str(ref ks) = &**k {
                            if let &MessageItem::Variant(ref vv) = &**v {
                                t.insert(ks.to_string(), (**vv).clone());
                            } else { haserr = true; };
                        } else { haserr = true; };
                    } else { haserr = true; };
                }
                if !haserr { return Ok(t) };
            }
        }
        let f = format!("Invalid reply for property GetAll: '{:?}'", reply);
        return Err(Error::new_custom("InvalidReply", &f));
    }
}

/// Wrapper around Props that keeps a map of fetched properties.
pub struct PropHandler<'a> {
    p: Props<'a>,
    map: BTreeMap<String, MessageItem>,
}

impl<'a> PropHandler<'a> {
    pub fn new(p: Props) -> PropHandler {
        PropHandler { p: p, map: BTreeMap::new() }
    }

    pub fn get_all(&mut self) -> Result<(), Error> {
        self.map = try!(self.p.get_all());
        Ok(())
    }

    pub fn map_mut(&mut self) -> &mut BTreeMap<String, MessageItem> { &mut self.map }
    pub fn map(&self) -> &BTreeMap<String, MessageItem> { &self.map }

    pub fn get(&mut self, propname: &str) -> Result<&MessageItem, Error> {
        let v = try!(self.p.get(propname));
        self.map.insert(propname.to_string(), v);
        Ok(self.map.get(propname).unwrap())
    }

    pub fn set(&mut self, propname: &str, value: MessageItem) -> Result<(), Error> {
        try!(self.p.set(propname, value.clone()));
        self.map.insert(propname.to_string(), value);
        Ok(())
    }
}

/* Unfortunately org.freedesktop.DBus has no properties we can use for testing, but PolicyKit should be around on most distros. */
#[test]
fn test_get_policykit_version() {
    use super::BusType;
    let c = Connection::get_private(BusType::System).unwrap();
    let p = Props::new(&c, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority",
        "org.freedesktop.PolicyKit1.Authority", 10000);

    /* Let's use both the get and getall methods and see if we get the same result */
    let v = p.get("BackendVersion").unwrap();
    let vall = p.get_all().unwrap();
    let v2 = vall.get("BackendVersion").unwrap();

    assert_eq!(&v, &*v2);
    match v {
        MessageItem::Str(ref s) => { println!("Policykit Backend version is {}", s); }
        _ => { panic!("Invalid Get: {:?}", v); }
    };
}

<|endoftext|>


<commit_before>//! Query result rows.

use fallible_iterator::FallibleIterator;
use postgres_protocol::message::frontend;
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt;
use std::io;
use std::ops::Deref;
use std::slice;

use {Result, SessionInfoNew, RowsNew, LazyRowsNew, StatementInternals, WrongTypeNew};
use transaction::Transaction;
use types::{FromSql, SessionInfo, WrongType};
use stmt::{Statement, Column};
use error::Error;

enum StatementContainer<'a> {
    Borrowed(&'a Statement<'a>),
    Owned(Statement<'a>),
}

impl<'a> Deref for StatementContainer<'a> {
    type Target = Statement<'a>;

    fn deref(&self) -> &Statement<'a> {
        match *self {
            StatementContainer::Borrowed(s) => s,
            StatementContainer::Owned(ref s) => s,
        }
    }
}

/// The resulting rows of a query.
pub struct Rows<'stmt> {
    stmt: StatementContainer<'stmt>,
    data: Vec<Vec<Option<Vec<u8>>>>,
}

impl<'a> RowsNew<'a> for Rows<'a> {
    fn new(stmt: &'a Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: StatementContainer::Borrowed(stmt),
            data: data,
        }
    }

    fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: StatementContainer::Owned(stmt),
            data: data,
        }
    }
}

impl<'a> fmt::Debug for Rows<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Rows")
            .field("columns", &self.columns())
            .field("rows", &self.data.len())
            .finish()
    }
}

impl<'stmt> Rows<'stmt> {
    /// Returns a slice describing the columns of the `Rows`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Returns the number of rows present.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any rows present.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a specific `Row`.
    ///
    /// # Panics
    ///
    /// Panics if `idx` is out of bounds.
    pub fn get<'a>(&'a self, idx: usize) -> Row<'a> {
        Row {
            stmt: &*self.stmt,
            data: Cow::Borrowed(&self.data[idx]),
        }
    }

    /// Returns an iterator over the `Row`s.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter {
            stmt: &*self.stmt,
            iter: self.data.iter(),
        }
    }
}

impl<'a> IntoIterator for &'a Rows<'a> {
    type Item = Row<'a>;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// An iterator over `Row`s.
pub struct Iter<'a> {
    stmt: &'a Statement<'a>,
    iter: slice::Iter<'a, Vec<Option<Vec<u8>>>>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        self.iter.next().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: Cow::Borrowed(row),
            }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<Row<'a>> {
        self.iter.next_back().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: Cow::Borrowed(row),
            }
        })
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

/// A single result row of a query.
pub struct Row<'a> {
    stmt: &'a Statement<'a>,
    data: Cow<'a, [Option<Vec<u8>>]>,
}

impl<'a> fmt::Debug for Row<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Row")
            .field("statement", self.stmt)
            .finish()
    }
}

impl<'a> Row<'a> {
    /// Returns the number of values in the row.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any values in the row.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a slice describing the columns of the `Row`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column or the return type is
    /// not compatible with the Postgres type.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// # use postgres::{Connection, TlsMode};
    /// # let conn = Connection::connect("", TlsMode::None).unwrap();
    /// let stmt = conn.prepare("SELECT foo, bar from BAZ").unwrap();
    /// for row in &stmt.query(&[]).unwrap() {
    ///     let foo: i32 = row.get(0);
    ///     let bar: String = row.get("bar");
    ///     println!("{}: {}", foo, bar);
    /// }
    /// ```
    pub fn get<I, T>(&self, idx: I) -> T
        where I: RowIndex + fmt::Debug,
              T: FromSql
    {
        match self.get_inner(&idx) {
            Some(Ok(ok)) => ok,
            Some(Err(err)) => panic!("error retrieving column {:?}: {:?}", idx, err),
            None => panic!("no such column {:?}", idx),
        }
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// Returns `None` if the index does not reference a column, `Some(Err(..))`
    /// if there was an error converting the result value, and `Some(Ok(..))`
    /// on success.
    pub fn get_opt<I, T>(&self, idx: I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        self.get_inner(&idx)
    }

    fn get_inner<I, T>(&self, idx: &I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        let idx = match idx.idx(self.stmt) {
            Some(idx) => idx,
            None => return None,
        };

        let ty = self.stmt.columns()[idx].type_();
        if !<T as FromSql>::accepts(ty) {
            return Some(Err(Error::Conversion(Box::new(WrongType::new(ty.clone())))));
        }
        let conn = self.stmt.conn().0.borrow();
        let value = FromSql::from_sql_nullable(ty,
                                               self.data[idx].as_ref().map(|r| &**r),
                                               &SessionInfo::new(&conn.parameters));
        Some(value.map_err(Error::Conversion))
    }

    /// Retrieves the specified field as a raw buffer of Postgres data.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column.
    pub fn get_bytes<I>(&self, idx: I) -> Option<&[u8]>
        where I: RowIndex + fmt::Debug
    {
        match idx.idx(self.stmt) {
            Some(idx) => self.data[idx].as_ref().map(|e| &**e),
            None => panic!("invalid index {:?}", idx),
        }
    }
}

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &Statement) -> Option<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if *self >= stmt.columns().len() {
            None
        } else {
            Some(*self)
        }
    }
}

impl<'a> RowIndex for &'a str {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if let Some(idx) = stmt.columns().iter().position(|d| d.name() == *self) {
            return Some(idx);
        };

        // FIXME ASCII-only case insensitivity isn't really the right thing to
        // do. Postgres itself uses a dubious wrapper around tolower and JDBC
        // uses the US locale.
        stmt.columns().iter().position(|d| d.name().eq_ignore_ascii_case(*self))
    }
}

/// A lazily-loaded iterator over the resulting rows of a query.
pub struct LazyRows<'trans, 'stmt> {
    stmt: &'stmt Statement<'stmt>,
    data: VecDeque<Vec<Option<Vec<u8>>>>,
    name: String,
    row_limit: i32,
    more_rows: bool,
    finished: bool,
    _trans: &'trans Transaction<'trans>,
}

impl<'trans, 'stmt> LazyRowsNew<'trans, 'stmt> for LazyRows<'trans, 'stmt> {
    fn new(stmt: &'stmt Statement<'stmt>,
           data: VecDeque<Vec<Option<Vec<u8>>>>,
           name: String,
           row_limit: i32,
           more_rows: bool,
           finished: bool,
           trans: &'trans Transaction<'trans>)
           -> LazyRows<'trans, 'stmt> {
        LazyRows {
            stmt: stmt,
            data: data,
            name: name,
            row_limit: row_limit,
            more_rows: more_rows,
            finished: finished,
            _trans: trans,
        }
    }
}

impl<'a, 'b> Drop for LazyRows<'a, 'b> {
    fn drop(&mut self) {
        if !self.finished {
            let _ = self.finish_inner();
        }
    }
}

impl<'a, 'b> fmt::Debug for LazyRows<'a, 'b> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("LazyRows")
            .field("name", &self.name)
            .field("row_limit", &self.row_limit)
            .field("remaining_rows", &self.data.len())
            .field("more_rows", &self.more_rows)
            .finish()
    }
}

impl<'trans, 'stmt> LazyRows<'trans, 'stmt> {
    fn finish_inner(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().0.borrow_mut();
        check_desync!(conn);
        conn.close_statement(&self.name, b'P')
    }

    fn execute(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().0.borrow_mut();

        try!(conn.stream.write_message(|buf| frontend::execute(&self.name, self.row_limit, buf)));
        try!(conn.stream.write_message(|buf| Ok::<(), io::Error>(frontend::sync(buf))));
        try!(conn.stream.flush());
        conn.read_rows(&mut self.data).map(|more_rows| self.more_rows = more_rows)
    }

    /// Returns a slice describing the columns of the `LazyRows`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Consumes the `LazyRows`, cleaning up associated state.
    ///
    /// Functionally identical to the `Drop` implementation on `LazyRows`
    /// except that it returns any error to the caller.
    pub fn finish(mut self) -> Result<()> {
        self.finish_inner()
    }
}

impl<'trans, 'stmt> FallibleIterator for LazyRows<'trans, 'stmt> {
    type Item = Row<'stmt>;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Row<'stmt>>> {
        if self.data.is_empty() && self.more_rows {
            try!(self.execute());
        }

        let row = self.data
            .pop_front()
            .map(|r| {
                Row {
                    stmt: self.stmt,
                    data: Cow::Owned(r),
                }
            });

        Ok(row)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let lower = self.data.len();
        let upper = if self.more_rows { None } else { Some(lower) };
        (lower, upper)
    }
}
<commit_msg>Generalize StatementContainer<commit_after>//! Query result rows.

use fallible_iterator::FallibleIterator;
use postgres_protocol::message::frontend;
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt;
use std::io;
use std::ops::Deref;
use std::slice;

use {Result, SessionInfoNew, RowsNew, LazyRowsNew, StatementInternals, WrongTypeNew};
use transaction::Transaction;
use types::{FromSql, SessionInfo, WrongType};
use stmt::{Statement, Column};
use error::Error;

enum MaybeOwned<'a, T: 'a> {
    Borrowed(&'a T),
    Owned(T),
}

impl<'a, T> Deref for MaybeOwned<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        match *self {
            MaybeOwned::Borrowed(s) => s,
            MaybeOwned::Owned(ref s) => s,
        }
    }
}

/// The resulting rows of a query.
pub struct Rows<'stmt> {
    stmt: MaybeOwned<'stmt, Statement<'stmt>>,
    data: Vec<Vec<Option<Vec<u8>>>>,
}

impl<'a> RowsNew<'a> for Rows<'a> {
    fn new(stmt: &'a Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: MaybeOwned::Borrowed(stmt),
            data: data,
        }
    }

    fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
        Rows {
            stmt: MaybeOwned::Owned(stmt),
            data: data,
        }
    }
}

impl<'a> fmt::Debug for Rows<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Rows")
            .field("columns", &self.columns())
            .field("rows", &self.data.len())
            .finish()
    }
}

impl<'stmt> Rows<'stmt> {
    /// Returns a slice describing the columns of the `Rows`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Returns the number of rows present.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any rows present.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a specific `Row`.
    ///
    /// # Panics
    ///
    /// Panics if `idx` is out of bounds.
    pub fn get<'a>(&'a self, idx: usize) -> Row<'a> {
        Row {
            stmt: &*self.stmt,
            data: MaybeOwned::Borrowed(&self.data[idx]),
        }
    }

    /// Returns an iterator over the `Row`s.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter {
            stmt: &*self.stmt,
            iter: self.data.iter(),
        }
    }
}

impl<'a> IntoIterator for &'a Rows<'a> {
    type Item = Row<'a>;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// An iterator over `Row`s.
pub struct Iter<'a> {
    stmt: &'a Statement<'a>,
    iter: slice::Iter<'a, Vec<Option<Vec<u8>>>>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Row<'a>;

    fn next(&mut self) -> Option<Row<'a>> {
        self.iter.next().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: MaybeOwned::Borrowed(row),
            }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<Row<'a>> {
        self.iter.next_back().map(|row| {
            Row {
                stmt: &*self.stmt,
                data: MaybeOwned::Borrowed(row),
            }
        })
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

/// A single result row of a query.
pub struct Row<'a> {
    stmt: &'a Statement<'a>,
    data: MaybeOwned<'a, Vec<Option<Vec<u8>>>>,
}

impl<'a> fmt::Debug for Row<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Row")
            .field("statement", self.stmt)
            .finish()
    }
}

impl<'a> Row<'a> {
    /// Returns the number of values in the row.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any values in the row.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a slice describing the columns of the `Row`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column or the return type is
    /// not compatible with the Postgres type.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// # use postgres::{Connection, TlsMode};
    /// # let conn = Connection::connect("", TlsMode::None).unwrap();
    /// let stmt = conn.prepare("SELECT foo, bar from BAZ").unwrap();
    /// for row in &stmt.query(&[]).unwrap() {
    ///     let foo: i32 = row.get(0);
    ///     let bar: String = row.get("bar");
    ///     println!("{}: {}", foo, bar);
    /// }
    /// ```
    pub fn get<I, T>(&self, idx: I) -> T
        where I: RowIndex + fmt::Debug,
              T: FromSql
    {
        match self.get_inner(&idx) {
            Some(Ok(ok)) => ok,
            Some(Err(err)) => panic!("error retrieving column {:?}: {:?}", idx, err),
            None => panic!("no such column {:?}", idx),
        }
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// Returns `None` if the index does not reference a column, `Some(Err(..))`
    /// if there was an error converting the result value, and `Some(Ok(..))`
    /// on success.
    pub fn get_opt<I, T>(&self, idx: I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        self.get_inner(&idx)
    }

    fn get_inner<I, T>(&self, idx: &I) -> Option<Result<T>>
        where I: RowIndex,
              T: FromSql
    {
        let idx = match idx.idx(self.stmt) {
            Some(idx) => idx,
            None => return None,
        };

        let ty = self.stmt.columns()[idx].type_();
        if !<T as FromSql>::accepts(ty) {
            return Some(Err(Error::Conversion(Box::new(WrongType::new(ty.clone())))));
        }
        let conn = self.stmt.conn().0.borrow();
        let value = FromSql::from_sql_nullable(ty,
                                               self.data[idx].as_ref().map(|r| &**r),
                                               &SessionInfo::new(&conn.parameters));
        Some(value.map_err(Error::Conversion))
    }

    /// Retrieves the specified field as a raw buffer of Postgres data.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column.
    pub fn get_bytes<I>(&self, idx: I) -> Option<&[u8]>
        where I: RowIndex + fmt::Debug
    {
        match idx.idx(self.stmt) {
            Some(idx) => self.data[idx].as_ref().map(|e| &**e),
            None => panic!("invalid index {:?}", idx),
        }
    }
}

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &Statement) -> Option<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if *self >= stmt.columns().len() {
            None
        } else {
            Some(*self)
        }
    }
}

impl<'a> RowIndex for &'a str {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Option<usize> {
        if let Some(idx) = stmt.columns().iter().position(|d| d.name() == *self) {
            return Some(idx);
        };

        // FIXME ASCII-only case insensitivity isn't really the right thing to
        // do. Postgres itself uses a dubious wrapper around tolower and JDBC
        // uses the US locale.
        stmt.columns().iter().position(|d| d.name().eq_ignore_ascii_case(*self))
    }
}

/// A lazily-loaded iterator over the resulting rows of a query.
pub struct LazyRows<'trans, 'stmt> {
    stmt: &'stmt Statement<'stmt>,
    data: VecDeque<Vec<Option<Vec<u8>>>>,
    name: String,
    row_limit: i32,
    more_rows: bool,
    finished: bool,
    _trans: &'trans Transaction<'trans>,
}

impl<'trans, 'stmt> LazyRowsNew<'trans, 'stmt> for LazyRows<'trans, 'stmt> {
    fn new(stmt: &'stmt Statement<'stmt>,
           data: VecDeque<Vec<Option<Vec<u8>>>>,
           name: String,
           row_limit: i32,
           more_rows: bool,
           finished: bool,
           trans: &'trans Transaction<'trans>)
           -> LazyRows<'trans, 'stmt> {
        LazyRows {
            stmt: stmt,
            data: data,
            name: name,
            row_limit: row_limit,
            more_rows: more_rows,
            finished: finished,
            _trans: trans,
        }
    }
}

impl<'a, 'b> Drop for LazyRows<'a, 'b> {
    fn drop(&mut self) {
        if !self.finished {
            let _ = self.finish_inner();
        }
    }
}

impl<'a, 'b> fmt::Debug for LazyRows<'a, 'b> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("LazyRows")
            .field("name", &self.name)
            .field("row_limit", &self.row_limit)
            .field("remaining_rows", &self.data.len())
            .field("more_rows", &self.more_rows)
            .finish()
    }
}

impl<'trans, 'stmt> LazyRows<'trans, 'stmt> {
    fn finish_inner(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().0.borrow_mut();
        check_desync!(conn);
        conn.close_statement(&self.name, b'P')
    }

    fn execute(&mut self) -> Result<()> {
        let mut conn = self.stmt.conn().0.borrow_mut();

        try!(conn.stream.write_message(|buf| frontend::execute(&self.name, self.row_limit, buf)));
        try!(conn.stream.write_message(|buf| Ok::<(), io::Error>(frontend::sync(buf))));
        try!(conn.stream.flush());
        conn.read_rows(&mut self.data).map(|more_rows| self.more_rows = more_rows)
    }

    /// Returns a slice describing the columns of the `LazyRows`.
    pub fn columns(&self) -> &[Column] {
        self.stmt.columns()
    }

    /// Consumes the `LazyRows`, cleaning up associated state.
    ///
    /// Functionally identical to the `Drop` implementation on `LazyRows`
    /// except that it returns any error to the caller.
    pub fn finish(mut self) -> Result<()> {
        self.finish_inner()
    }
}

impl<'trans, 'stmt> FallibleIterator for LazyRows<'trans, 'stmt> {
    type Item = Row<'stmt>;
    type Error = Error;

    fn next(&mut self) -> Result<Option<Row<'stmt>>> {
        if self.data.is_empty() && self.more_rows {
            try!(self.execute());
        }

        let row = self.data
            .pop_front()
            .map(|r| {
                Row {
                    stmt: self.stmt,
                    data: MaybeOwned::Owned(r),
                }
            });

        Ok(row)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let lower = self.data.len();
        let upper = if self.more_rows { None } else { Some(lower) };
        (lower, upper)
    }
}
<|endoftext|>


<commit_before>#[link_args="-ledit -ltermcap"]
use libc::{c_char};
extern mod edit {
    fn el_init(argv: **c_char, stdin: io::Reader, stdout: io::Writer, stderr: io::Writer) -> *u8;
    fn el_set(el: *u8, param: libc::c_int, val: ~str);
}
pub const EL_EDITOR: libc::c_int = 2_i32;
fn main() {
    let args = os::args().map(|arg| str::as_c_str(*arg, |buf| buf));
    unsafe {
        let el = edit::el_init(vec::raw::to_ptr(args), io::stdin(), io::stdout(), io::stderr());
        let editor = ~"vi";
        edit::el_set(el, EL_EDITOR, editor);
    }
}
<commit_msg>Actually run things!<commit_after>extern mod linenoise;

fn handle_input(line: ~str) {
    linenoise::history_add(line);
    linenoise::history_save("history.txt");
    let split_line = str::split_char(line, ' ');
    let command = split_line.head();
    let args = split_line.tail();
    core::run::run_program(*command, args);
}

fn main() {
    linenoise::set_multiline(true);
    loop {
        let line = linenoise::init("rush: ");
        handle_input(line);
    }
}
<|endoftext|>


<commit_before>// (c) 2016 Productize SPRL <joost@productize.be>

use std::fmt;
use std::result;
use std::str::FromStr;

use str_error;
use Result;

// like Into trait but works from a ref avoiding consumption or expensive clone
pub trait IntoSexp {
    fn into_sexp(&self) -> Sexp;
}

#[derive(Debug, Clone)]
pub enum Sexp {
    String(String),
    List(Vec<Sexp>),
    Empty,
}

/*

Following the KiCad file formats specification chapter 4.4 - Identifiers and Strings:
A string may not contain an actual newline or carriage return, but it may use an escape sequence to encode a
newline, such as \n.
If a string has any of the following conditions, then it must be quoted with a leading and trailing double quote
character, otherwise it is acceptable to not quote the string:
1. has one or more of the following 4 separator bytes: ASCII space, tab, '(', or ')'.
2. has one or more of the following bytes: '%', '{', or '}'.
3. has a length of zero bytes, and you need a place holder for the field, then use "".
4. includes a byte of '-', and this byte is not in the first position of the string.
*/

pub fn encode_string(s:&str) -> String {
    fn rule_4(s:&str) -> bool {
        s.contains('-') && s.len() > 1 && s.as_bytes()[0] != 45
    }
    if s.contains('(') || s.contains(' ') || s.contains(')') || s.contains('\t') || s.contains('{') || s.contains('}') || s.contains('}') || s.contains('%') || s.is_empty() || rule_4(s) {
        format!("\"{}\"", s)
    } else {
        String::from(s)
    }
}

impl Sexp {

    pub fn new_empty() -> Sexp {
        Sexp::Empty
    }

    pub fn new_string<T>(s:T) -> Sexp where T:fmt::Display {
        Sexp::String(format!("{}", s))
    }

    pub fn new_list(v:Vec<Sexp>) -> Sexp {
        Sexp::List(v)
    }

    pub fn new_named<T>(name:&str, value:T) -> Sexp where T:fmt::Display {
        let v = vec![Sexp::new_string(name), Sexp::new_string(value)];
        Sexp::List(v)
    }

    pub fn from<T:IntoSexp>(t:&T) -> Sexp {
        t.into_sexp()
    }

    pub fn list(&self) -> Result<&Vec<Sexp> > {
        match *self {
            Sexp::List(ref v) => Ok(v),
            _ => str_error(format!("not a list: {}", self))
        }
    }

    pub fn string(&self) -> Result<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            _ => str_error(format!("not a string: {}", self))
        }
    }

    pub fn f(&self) -> Result<f64> {
        let s = try!(self.string());
        match f64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing float".to_string())
        }
    }

    pub fn i(&self) -> Result<i64> {
        let s = try!(self.string());
        match i64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing int".to_string())
        }
    }

    pub fn list_name(&self) -> Result<&String> {
        let l = try!(self.list());
        let l = &l[..];
        let a = try!(l[0].string());
        Ok(a)
    }

    pub fn slice_atom(&self, s:&str) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list {} doesn't start with {}, but with {}", self, s, st))
        };
        Ok(&v[1..])
    }

    pub fn named_value(&self, s:&str) -> Result<&Sexp> {
        let v = try!(self.list());
        if v.len() != 2 {
            return str_error(format!("list {} is not a named_value", s))
        }
        let l = try!(self.slice_atom(s));
        Ok(&l[0])
    }

    pub fn named_value_i(&self, s:&str) -> Result<i64> {
        try!(self.named_value(s)).i()
    }

    pub fn named_value_f(&self, s:&str) -> Result<f64> {
        try!(self.named_value(s)).f()
    }

    pub fn named_value_string(&self, s:&str) -> Result<&String> {
        try!(self.named_value(s)).string()
    }

    pub fn slice_atom_num(&self, s:&str, num:usize) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list doesn't start with {}, but with {}", s, st))
        };
        if v.len() != (num+1) {
            return str_error(format!("list ({}) doesn't have {} elements but {}", s, num, v.len()-1))
        }
        Ok(&v[1..])
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            Sexp::String(ref s) => {
                write!(f, "{}", encode_string(s))
            },
            Sexp::List(ref v) => {
                try!(write!(f, "("));
                let l = v.len();
                for (i,x) in v.iter().enumerate() {
                    if i < l-1 {
                        try!(write!(f, "{} ", x));
                    } else {
                        try!(write!(f, "{}", x));
                    }
                }
                write!(f, ")")
            },
            Sexp::Empty => Ok(())
        }
    }
}
<commit_msg>new_named_sexp<commit_after>// (c) 2016 Productize SPRL <joost@productize.be>

use std::fmt;
use std::result;
use std::str::FromStr;

use str_error;
use Result;

// like Into trait but works from a ref avoiding consumption or expensive clone
pub trait IntoSexp {
    fn into_sexp(&self) -> Sexp;
}

#[derive(Debug, Clone)]
pub enum Sexp {
    String(String),
    List(Vec<Sexp>),
    Empty,
}

/*

Following the KiCad file formats specification chapter 4.4 - Identifiers and Strings:
A string may not contain an actual newline or carriage return, but it may use an escape sequence to encode a
newline, such as \n.
If a string has any of the following conditions, then it must be quoted with a leading and trailing double quote
character, otherwise it is acceptable to not quote the string:
1. has one or more of the following 4 separator bytes: ASCII space, tab, '(', or ')'.
2. has one or more of the following bytes: '%', '{', or '}'.
3. has a length of zero bytes, and you need a place holder for the field, then use "".
4. includes a byte of '-', and this byte is not in the first position of the string.
*/

pub fn encode_string(s:&str) -> String {
    fn rule_4(s:&str) -> bool {
        s.contains('-') && s.len() > 1 && s.as_bytes()[0] != 45
    }
    if s.contains('(') || s.contains(' ') || s.contains(')') || s.contains('\t') || s.contains('{') || s.contains('}') || s.contains('}') || s.contains('%') || s.is_empty() || rule_4(s) {
        format!("\"{}\"", s)
    } else {
        String::from(s)
    }
}

impl Sexp {

    pub fn new_empty() -> Sexp {
        Sexp::Empty
    }

    pub fn new_string<T>(s:T) -> Sexp where T:fmt::Display {
        Sexp::String(format!("{}", s))
    }

    pub fn new_list(v:Vec<Sexp>) -> Sexp {
        Sexp::List(v)
    }

    pub fn new_named<T>(name:&str, value:T) -> Sexp where T:fmt::Display {
        let mut v = vec![];
        v.push(Sexp::new_string(name));
        v.push(Sexp::new_string(value));
        Sexp::List(v)
    }

    pub fn new_named_sexp<T>(name:&str, value:T) -> Sexp where T:IntoSexp {
        let mut v = vec![];
        v.push(Sexp::new_string(name));
        v.push(value.into_sexp());
        Sexp::List(v)
    }

    pub fn from<T:IntoSexp>(t:&T) -> Sexp {
        t.into_sexp()
    }

    pub fn list(&self) -> Result<&Vec<Sexp> > {
        match *self {
            Sexp::List(ref v) => Ok(v),
            _ => str_error(format!("not a list: {}", self))
        }
    }

    pub fn string(&self) -> Result<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            _ => str_error(format!("not a string: {}", self))
        }
    }

    pub fn f(&self) -> Result<f64> {
        let s = try!(self.string());
        match f64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing float".to_string())
        }
    }

    pub fn i(&self) -> Result<i64> {
        let s = try!(self.string());
        match i64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing int".to_string())
        }
    }

    pub fn list_name(&self) -> Result<&String> {
        let l = try!(self.list());
        let l = &l[..];
        let a = try!(l[0].string());
        Ok(a)
    }

    pub fn slice_atom(&self, s:&str) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list {} doesn't start with {}, but with {}", self, s, st))
        };
        Ok(&v[1..])
    }

    pub fn named_value(&self, s:&str) -> Result<&Sexp> {
        let v = try!(self.list());
        if v.len() != 2 {
            return str_error(format!("list {} is not a named_value", s))
        }
        let l = try!(self.slice_atom(s));
        Ok(&l[0])
    }

    pub fn named_value_i(&self, s:&str) -> Result<i64> {
        try!(self.named_value(s)).i()
    }

    pub fn named_value_f(&self, s:&str) -> Result<f64> {
        try!(self.named_value(s)).f()
    }

    pub fn named_value_string(&self, s:&str) -> Result<&String> {
        try!(self.named_value(s)).string()
    }

    pub fn slice_atom_num(&self, s:&str, num:usize) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list doesn't start with {}, but with {}", s, st))
        };
        if v.len() != (num+1) {
            return str_error(format!("list ({}) doesn't have {} elements but {}", s, num, v.len()-1))
        }
        Ok(&v[1..])
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            Sexp::String(ref s) => {
                write!(f, "{}", encode_string(s))
            },
            Sexp::List(ref v) => {
                try!(write!(f, "("));
                let l = v.len();
                for (i,x) in v.iter().enumerate() {
                    if i < l-1 {
                        try!(write!(f, "{} ", x));
                    } else {
                        try!(write!(f, "{}", x));
                    }
                }
                write!(f, ")")
            },
            Sexp::Empty => Ok(())
        }
    }
}
<|endoftext|>


<commit_before>use libc::*;
use std::{mem, cmp, ptr, slice};

use miniz_oxide::deflate::core::{compress, compress_to_output, create_comp_flags_from_zip_params,
                           CallbackFunc, CompressorOxide, PutBufFuncPtr, TDEFLFlush, TDEFLStatus};

#[repr(C)]
#[allow(bad_style)]
pub struct tdefl_compressor {
    pub inner: CompressorOxide,
    pub callback: Option<CallbackFunc>,
}

impl tdefl_compressor {
    pub(crate) fn new(flags: u32) -> Self {
        tdefl_compressor {
            inner: CompressorOxide::new(flags),
            callback: None,
        }
    }

    pub(crate) fn new_with_callback(flags: u32, func: CallbackFunc) -> Self {
        tdefl_compressor {
            inner: CompressorOxide::new(flags),
            callback: Some(func),
        }
    }

    pub fn adler32(&self) -> u32 {
        self.inner.adler32()
    }

    pub fn prev_return_status(&self) -> TDEFLStatus {
        self.inner.prev_return_status()
    }

    pub fn flags(&self) -> i32 {
        self.inner.flags()
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress(
    d: Option<&mut tdefl_compressor>,
    in_buf: *const c_void,
    in_size: Option<&mut usize>,
    out_buf: *mut c_void,
    out_size: Option<&mut usize>,
    flush: TDEFLFlush,
) -> TDEFLStatus {
    match d {
        None => {
            in_size.map(|size| *size = 0);
            out_size.map(|size| *size = 0);
            TDEFLStatus::BadParam
        },
        Some(compressor) => {
            let in_buf_size = in_size.as_ref().map_or(0, |size| **size);
            let out_buf_size = out_size.as_ref().map_or(0, |size| **size);

            if in_buf_size > 0 && in_buf.is_null() {
                in_size.map(|size| *size = 0);
                out_size.map(|size| *size = 0);
                return TDEFLStatus::BadParam;
            }

            let in_slice = (in_buf as *const u8).as_ref().map_or(&[][..],|in_buf| {
                slice::from_raw_parts(in_buf, in_buf_size)
            });

            let res = match compressor.callback {
                None => {
                    match (out_buf as *mut u8).as_mut() {
                        Some(out_buf) => compress(
                            &mut compressor.inner,
                            in_slice,
                            slice::from_raw_parts_mut(out_buf, out_buf_size),
                            flush,
                        ),
                        None => {
                            in_size.map(|size| *size = 0);
                            out_size.map(|size| *size = 0);
                            return TDEFLStatus::BadParam;
                        }
                    }
                },
                Some(func) => {
                    if out_buf_size > 0 || !out_buf.is_null() {
                        in_size.map(|size| *size = 0);
                        out_size.map(|size| *size = 0);
                        return TDEFLStatus::BadParam;
                    }
                    compress_to_output(&mut compressor.inner, in_slice, func, flush)
                },
            };

            in_size.map(|size| *size = res.1);
            out_size.map(|size| *size = res.2);
            res.0
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_buffer(
    d: Option<&mut tdefl_compressor>,
    in_buf: *const c_void,
    mut in_size: usize,
    flush: TDEFLFlush,
) -> TDEFLStatus {
    tdefl_compress(d, in_buf, Some(&mut in_size), ptr::null_mut(), None, flush)
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_init(
    d: Option<&mut tdefl_compressor>,
    put_buf_func: PutBufFuncPtr,
    put_buf_user: *mut c_void,
    flags: c_int,
) -> TDEFLStatus {
    if let Some(d) = d {
        *d = put_buf_func.map_or(tdefl_compressor::new(flags as u32), |f| {
            tdefl_compressor::new_with_callback(flags as u32, CallbackFunc {
                put_buf_func: f,
                put_buf_user: put_buf_user,
            })
        });
        TDEFLStatus::Okay
    } else {
        TDEFLStatus::BadParam
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_get_prev_return_status(
    d: Option<&mut tdefl_compressor>,
) -> TDEFLStatus {
    d.map_or(TDEFLStatus::Okay, |d| d.inner.prev_return_status())
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_get_adler32(d: Option<&mut tdefl_compressor>) -> c_uint {
    d.map_or(::MZ_ADLER32_INIT as u32, |d| d.inner.adler32())
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_mem_to_output(
    buf: *const c_void,
    buf_len: usize,
    put_buf_func: PutBufFuncPtr,
    put_buf_user: *mut c_void,
    flags: c_int,
) -> bool {
    if let Some(put_buf_func) = put_buf_func {
        let compressor = ::miniz_def_alloc_func(
            ptr::null_mut(),
            1,
            mem::size_of::<CompressorOxide>(),
        ) as *mut tdefl_compressor;

        *compressor = tdefl_compressor::new_with_callback(flags as u32, CallbackFunc {
            put_buf_func: put_buf_func,
            put_buf_user: put_buf_user,
        });

        let res = tdefl_compress_buffer(compressor.as_mut(), buf, buf_len, TDEFLFlush::Finish) ==
            TDEFLStatus::Done;
        ::miniz_def_free_func(ptr::null_mut(), compressor as *mut c_void);
        res
    } else {
        false
    }
}

struct BufferUser {
    pub size: usize,
    pub capacity: usize,
    pub buf: *mut u8,
    pub expandable: bool,
}

pub unsafe extern "C" fn output_buffer_putter(
    buf: *const c_void,
    len: c_int,
    user: *mut c_void,
) -> bool {
    let user = (user as *mut BufferUser).as_mut();
    match user {
        None => false,
        Some(user) => {
            let new_size = user.size + len as usize;
            if new_size > user.capacity {
                if !user.expandable {
                    return false;
                }
                let mut new_capacity = cmp::max(user.capacity, 128);
                while new_size > new_capacity {
                    new_capacity <<= 1;
                }

                let new_buf = ::miniz_def_realloc_func(
                    ptr::null_mut(),
                    user.buf as *mut c_void,
                    1,
                    new_capacity,
                );

                if new_buf.is_null() {
                    return false;
                }

                user.buf = new_buf as *mut u8;
                user.capacity = new_capacity;
            }

            ptr::copy_nonoverlapping(
                buf as *const u8,
                user.buf.offset(user.size as isize),
                len as usize,
            );
            user.size = new_size;
            true
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_mem_to_heap(
    src_buf: *const c_void,
    src_buf_len: usize,
    out_len: *mut usize,
    flags: c_int,
) -> *mut c_void {
    match out_len.as_mut() {
        None => ptr::null_mut(),
        Some(len) => {
            *len = 0;

            let mut buffer_user = BufferUser {
                size: 0,
                capacity: 0,
                buf: ptr::null_mut(),
                expandable: true,
            };

            if !tdefl_compress_mem_to_output(
                src_buf,
                src_buf_len,
                Some(output_buffer_putter),
                &mut buffer_user as *mut BufferUser as *mut c_void,
                flags,
            )
            {
                ptr::null_mut()
            } else {
                *len = buffer_user.size;
                buffer_user.buf as *mut c_void
            }
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_mem_to_mem(
    out_buf: *mut c_void,
    out_buf_len: usize,
    src_buf: *const c_void,
    src_buf_len: usize,
    flags: c_int,
) -> usize {
    if out_buf.is_null() {
        return 0;
    }
    let mut buffer_user = BufferUser {
        size: 0,
        capacity: out_buf_len,
        buf: out_buf as *mut u8,
        expandable: false,
    };

    if tdefl_compress_mem_to_output(
        src_buf,
        src_buf_len,
        Some(output_buffer_putter),
        &mut buffer_user as *mut BufferUser as *mut c_void,
        flags,
    )
    {
        buffer_user.size
    } else {
        0
    }
}

#[no_mangle]
pub extern "C" fn tdefl_create_comp_flags_from_zip_params(
    level: c_int,
    window_bits: c_int,
    strategy: c_int,
) -> c_uint {
    create_comp_flags_from_zip_params(level, window_bits, strategy)
}
<commit_msg>fix alloc<commit_after>use libc::*;
use std::{mem, cmp, ptr, slice};

use miniz_oxide::deflate::core::{compress, compress_to_output, create_comp_flags_from_zip_params,
                           CallbackFunc, CompressorOxide, PutBufFuncPtr, TDEFLFlush, TDEFLStatus};

#[repr(C)]
#[allow(bad_style)]
pub struct tdefl_compressor {
    pub inner: CompressorOxide,
    pub callback: Option<CallbackFunc>,
}

impl tdefl_compressor {
    pub(crate) fn new(flags: u32) -> Self {
        tdefl_compressor {
            inner: CompressorOxide::new(flags),
            callback: None,
        }
    }

    pub(crate) fn new_with_callback(flags: u32, func: CallbackFunc) -> Self {
        tdefl_compressor {
            inner: CompressorOxide::new(flags),
            callback: Some(func),
        }
    }

    pub fn adler32(&self) -> u32 {
        self.inner.adler32()
    }

    pub fn prev_return_status(&self) -> TDEFLStatus {
        self.inner.prev_return_status()
    }

    pub fn flags(&self) -> i32 {
        self.inner.flags()
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress(
    d: Option<&mut tdefl_compressor>,
    in_buf: *const c_void,
    in_size: Option<&mut usize>,
    out_buf: *mut c_void,
    out_size: Option<&mut usize>,
    flush: TDEFLFlush,
) -> TDEFLStatus {
    match d {
        None => {
            in_size.map(|size| *size = 0);
            out_size.map(|size| *size = 0);
            TDEFLStatus::BadParam
        },
        Some(compressor) => {
            let in_buf_size = in_size.as_ref().map_or(0, |size| **size);
            let out_buf_size = out_size.as_ref().map_or(0, |size| **size);

            if in_buf_size > 0 && in_buf.is_null() {
                in_size.map(|size| *size = 0);
                out_size.map(|size| *size = 0);
                return TDEFLStatus::BadParam;
            }

            let in_slice = (in_buf as *const u8).as_ref().map_or(&[][..],|in_buf| {
                slice::from_raw_parts(in_buf, in_buf_size)
            });

            let res = match compressor.callback {
                None => {
                    match (out_buf as *mut u8).as_mut() {
                        Some(out_buf) => compress(
                            &mut compressor.inner,
                            in_slice,
                            slice::from_raw_parts_mut(out_buf, out_buf_size),
                            flush,
                        ),
                        None => {
                            in_size.map(|size| *size = 0);
                            out_size.map(|size| *size = 0);
                            return TDEFLStatus::BadParam;
                        }
                    }
                },
                Some(func) => {
                    if out_buf_size > 0 || !out_buf.is_null() {
                        in_size.map(|size| *size = 0);
                        out_size.map(|size| *size = 0);
                        return TDEFLStatus::BadParam;
                    }
                    compress_to_output(&mut compressor.inner, in_slice, func, flush)
                },
            };

            in_size.map(|size| *size = res.1);
            out_size.map(|size| *size = res.2);
            res.0
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_buffer(
    d: Option<&mut tdefl_compressor>,
    in_buf: *const c_void,
    mut in_size: usize,
    flush: TDEFLFlush,
) -> TDEFLStatus {
    tdefl_compress(d, in_buf, Some(&mut in_size), ptr::null_mut(), None, flush)
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_init(
    d: Option<&mut tdefl_compressor>,
    put_buf_func: PutBufFuncPtr,
    put_buf_user: *mut c_void,
    flags: c_int,
) -> TDEFLStatus {
    if let Some(d) = d {
        *d = put_buf_func.map_or(tdefl_compressor::new(flags as u32), |f| {
            tdefl_compressor::new_with_callback(flags as u32, CallbackFunc {
                put_buf_func: f,
                put_buf_user: put_buf_user,
            })
        });
        TDEFLStatus::Okay
    } else {
        TDEFLStatus::BadParam
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_get_prev_return_status(
    d: Option<&mut tdefl_compressor>,
) -> TDEFLStatus {
    d.map_or(TDEFLStatus::Okay, |d| d.inner.prev_return_status())
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_get_adler32(d: Option<&mut tdefl_compressor>) -> c_uint {
    d.map_or(::MZ_ADLER32_INIT as u32, |d| d.inner.adler32())
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_mem_to_output(
    buf: *const c_void,
    buf_len: usize,
    put_buf_func: PutBufFuncPtr,
    put_buf_user: *mut c_void,
    flags: c_int,
) -> bool {
    if let Some(put_buf_func) = put_buf_func {
        let compressor = ::miniz_def_alloc_func(
            ptr::null_mut(),
            1,
            mem::size_of::<tdefl_compressor>(),
        ) as *mut tdefl_compressor;

        *compressor = tdefl_compressor::new_with_callback(flags as u32, CallbackFunc {
            put_buf_func: put_buf_func,
            put_buf_user: put_buf_user,
        });

        let res = tdefl_compress_buffer(compressor.as_mut(), buf, buf_len, TDEFLFlush::Finish) ==
            TDEFLStatus::Done;
        ::miniz_def_free_func(ptr::null_mut(), compressor as *mut c_void);
        res
    } else {
        false
    }
}

struct BufferUser {
    pub size: usize,
    pub capacity: usize,
    pub buf: *mut u8,
    pub expandable: bool,
}

pub unsafe extern "C" fn output_buffer_putter(
    buf: *const c_void,
    len: c_int,
    user: *mut c_void,
) -> bool {
    let user = (user as *mut BufferUser).as_mut();
    match user {
        None => false,
        Some(user) => {
            let new_size = user.size + len as usize;
            if new_size > user.capacity {
                if !user.expandable {
                    return false;
                }
                let mut new_capacity = cmp::max(user.capacity, 128);
                while new_size > new_capacity {
                    new_capacity <<= 1;
                }

                let new_buf = ::miniz_def_realloc_func(
                    ptr::null_mut(),
                    user.buf as *mut c_void,
                    1,
                    new_capacity,
                );

                if new_buf.is_null() {
                    return false;
                }

                user.buf = new_buf as *mut u8;
                user.capacity = new_capacity;
            }

            ptr::copy_nonoverlapping(
                buf as *const u8,
                user.buf.offset(user.size as isize),
                len as usize,
            );
            user.size = new_size;
            true
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_mem_to_heap(
    src_buf: *const c_void,
    src_buf_len: usize,
    out_len: *mut usize,
    flags: c_int,
) -> *mut c_void {
    match out_len.as_mut() {
        None => ptr::null_mut(),
        Some(len) => {
            *len = 0;

            let mut buffer_user = BufferUser {
                size: 0,
                capacity: 0,
                buf: ptr::null_mut(),
                expandable: true,
            };

            if !tdefl_compress_mem_to_output(
                src_buf,
                src_buf_len,
                Some(output_buffer_putter),
                &mut buffer_user as *mut BufferUser as *mut c_void,
                flags,
            ) {
                ptr::null_mut()
            } else {
                *len = buffer_user.size;
                buffer_user.buf as *mut c_void
            }
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn tdefl_compress_mem_to_mem(
    out_buf: *mut c_void,
    out_buf_len: usize,
    src_buf: *const c_void,
    src_buf_len: usize,
    flags: c_int,
) -> usize {
    if out_buf.is_null() {
        return 0;
    }
    let mut buffer_user = BufferUser {
        size: 0,
        capacity: out_buf_len,
        buf: out_buf as *mut u8,
        expandable: false,
    };

    if tdefl_compress_mem_to_output(
        src_buf,
        src_buf_len,
        Some(output_buffer_putter),
        &mut buffer_user as *mut BufferUser as *mut c_void,
        flags,
    )
    {
        buffer_user.size
    } else {
        0
    }
}

#[no_mangle]
pub extern "C" fn tdefl_create_comp_flags_from_zip_params(
    level: c_int,
    window_bits: c_int,
    strategy: c_int,
) -> c_uint {
    create_comp_flags_from_zip_params(level, window_bits, strategy)
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use serde_json::Value;

use renderer::*;

const LINE_HEIGHT: f32 = 20.;
const LEFT_MARGIN: f32 = 15.;

// #[derive(Clone)]
pub struct Line<'a> {
    pub text: String,
    pub cursor: Option<u64>,
    selection: Option<(u64,u64)>,
    pub renderer: LineRenderer<'a>, // This is the lifetime that infects the hierarchy up to State
}

impl<'a> Line<'a> {

    pub fn placeholder(renderer: &'a Renderer) -> Line<'a> {
        let text = ">>> NOT IN CACHE <<<";
        let renderer = LineRenderer::new(renderer, text);
        Line { text: text.into(), cursor: None, selection: None, renderer: renderer }
    }
}

pub struct Text<'a> {
    cache: BTreeMap<u64, Line<'a>>,
    placeholder_line: Line<'a>,
    pub top: f64,
    pub height: f64,
    n_lines: u64,
    renderer: TextRenderer,
    // scrollbar: Primitive,
}

impl<'a> Text<'a> {
    pub fn new(renderer: &Renderer) -> Text {
        Text {
            cache: BTreeMap::new(),
            placeholder_line: Line::placeholder(renderer),
            top: 0.,
            height: 0.,
            n_lines: 0,
            renderer: TextRenderer::new(renderer, LEFT_MARGIN)
        }
    }

    pub fn refresh(&mut self, n_lines: u64) {
        self.cache.clear();
        self.n_lines = n_lines;
    }

    pub fn render(&self, target: &mut Target) {
        self.renderer.draw(target, &self.get_lines(), self.top, self.height, self.n_lines);
    }

    pub fn add_lines(&mut self, renderer: &'a Renderer, value: &Value, first: u64) {
        for (i, line) in value.as_array().unwrap().into_iter().enumerate() {
            let line = line.as_array().unwrap();
            let text = line[0].as_string().unwrap().to_string();
            // annotations
            let mut cursor = None;
            let mut selection = None;
            for annotation in line.iter().skip(1).map(|a| a.as_array().unwrap()) {
                match annotation[0].as_string().unwrap() {
                    "cursor" => {
                        cursor = Some(annotation[1].as_u64().unwrap());
                    },
                    "sel" => {
                        selection = Some((annotation[1].as_u64().unwrap(), annotation[2].as_u64().unwrap()));
                    }, _ => () // ignore unknown annotations
                }
            }
            let renderer = LineRenderer::new(renderer, &text);
            self.cache.insert(i as u64+first, Line { text: text, cursor: cursor, selection: selection, renderer: renderer });
        }
    }

    pub fn scroll_to(&mut self, line: u64, _column: u64) {
        let min = |a,b| if a > b { b } else { a };
        let max = |a,b| if a < b { b } else { a };
        self.top = max(0., min(self.top, line as f64 - 2.)); // scroll up
        self.top = min(self.n_lines as f64, max(self.top, line as f64 - self.height + 1. + 2.)); // scroll dn
    }

    pub fn scroll(&mut self, delta_y: f64) {
        let y = self.top + delta_y;
        let max = self.n_lines as f64 - self.height;
        self.top = if y > max { max }
        else if y < 0. { 0. }
        else { y };
    }

    pub fn get_lines(&self) -> Vec<(f32, &Line)> {
        self.get_line_pos().into_iter().filter_map(|(pos,i)| self.get_line(i).map(|x| (pos,x))).collect()
    }

    // Return: Vec<(line_pos, line_id)>
    pub fn get_line_pos(&self) -> Vec<(f32, u64)> {
        (self.top as u64 .. (self.top + self.height).ceil() as u64)
            .map(|i| ((self.height - i as f64 + self.top - 0.5) as f32 * LINE_HEIGHT, i)
            ).collect()
    }

    pub fn get_line_col(&self, px: i32, py: i32) -> (u64,u64) {
        let line = self.get_line_pos().into_iter().min_by_key(|&(y,_)| (y as i32 - py).abs()).unwrap().1;
        let column = if let Some(line) = self.get_line(line) {
            line.renderer.char_pos_x.iter().enumerate().min_by_key(|&(_,x)| {
                (*x as i32 - px + LEFT_MARGIN as i32).abs()
            }).unwrap().0 as u64
        } else { // after the text
            0
        };
        (line, column)
    }

    fn get_line(&self, n: u64) -> Option<&Line> {
        if n >= self.n_lines {
            None
        } else {
            Some(self.cache.get(&n).unwrap_or(&self.placeholder_line))
        }
    }

    pub fn set_size(&mut self, _w: u32, h: u32) {
        self.height = h as f64 / LINE_HEIGHT as f64;
    }
}

pub struct TextRenderer {
    cursor: Primitive,
    line_bg: Primitive,
    left_margin: f32,
}

impl TextRenderer {
    pub fn new(renderer: &Renderer, left_margin: f32) -> TextRenderer {
        let cursor = Primitive::new_line(&renderer, (0.,-10.), (0.,10.), [0.,0.,0.,1.]);
        let line_bg = Primitive::new_rect(&renderer, (0., -10.), (2000., 10.), [1.,1.,0.7,1.]);

        TextRenderer { cursor: cursor, line_bg: line_bg, left_margin: left_margin }
    }

    pub fn draw_line(&self, target: &mut Target, line: &Line, (px, py): (f32, f32)) {
        let offset = |pos| {
            let ch_pos_x = &line.renderer.char_pos_x;
            ch_pos_x[::std::cmp::min(pos as usize, ch_pos_x.len() - 1)]
        };

        if let Some(pos) = line.cursor {
            self.line_bg.draw(target, (px, py)).unwrap();
            self.cursor.draw(target, (offset(pos) + px, py)).unwrap();
        }

        if let Some(sel) = line.selection {
            let selection_bg = Primitive::new_rect(&target.renderer,
                (offset(sel.0) as f32 + px, -10.),
                (offset(sel.1) as f32 + px, 10.),
                [0.5,0.5,1.,1.]);
            selection_bg.draw(target, (0.,py)).unwrap();
        }

        line.renderer.draw(target, px, py);
    }

    pub fn draw(&self, target: &mut Target, lines: &[(f32,&Line)], top: f64, height: f64, n_lines: u64) {
        for &(y, line) in lines {
            self.draw_line(target, &line, (self.left_margin, y));
        }

        // draw scrollbar
        let dims = target.get_dimensions();
        let (w, h) = (dims.0 as f32, dims.1 as f32);
        let (rel_y, rel_h) = (top / n_lines as f64, height / n_lines as f64);
        let scrollbar = Primitive::new_rect(&target.renderer,
            (w - 20., h - rel_y as f32 * h), (w, h - (rel_y + rel_h) as f32 * h),
            [0.5,0.5,0.5,1.]);
        scrollbar.draw(target, (0.,0.)).unwrap();
    }
}
<commit_msg>Fix mouse scroll if the text fits on the screen<commit_after>use std::collections::BTreeMap;
use serde_json::Value;

use renderer::*;

const LINE_HEIGHT: f32 = 20.;
const LEFT_MARGIN: f32 = 15.;

// #[derive(Clone)]
pub struct Line<'a> {
    pub text: String,
    pub cursor: Option<u64>,
    selection: Option<(u64,u64)>,
    pub renderer: LineRenderer<'a>, // This is the lifetime that infects the hierarchy up to State
}

impl<'a> Line<'a> {

    pub fn placeholder(renderer: &'a Renderer) -> Line<'a> {
        let text = ">>> NOT IN CACHE <<<";
        let renderer = LineRenderer::new(renderer, text);
        Line { text: text.into(), cursor: None, selection: None, renderer: renderer }
    }
}

pub struct Text<'a> {
    cache: BTreeMap<u64, Line<'a>>,
    placeholder_line: Line<'a>,
    pub top: f64,
    pub height: f64,
    n_lines: u64,
    renderer: TextRenderer,
    // scrollbar: Primitive,
}

impl<'a> Text<'a> {
    pub fn new(renderer: &Renderer) -> Text {
        Text {
            cache: BTreeMap::new(),
            placeholder_line: Line::placeholder(renderer),
            top: 0.,
            height: 0.,
            n_lines: 0,
            renderer: TextRenderer::new(renderer, LEFT_MARGIN)
        }
    }

    pub fn refresh(&mut self, n_lines: u64) {
        self.cache.clear();
        self.n_lines = n_lines;
    }

    pub fn render(&self, target: &mut Target) {
        self.renderer.draw(target, &self.get_lines(), self.top, self.height, self.n_lines);
    }

    pub fn add_lines(&mut self, renderer: &'a Renderer, value: &Value, first: u64) {
        for (i, line) in value.as_array().unwrap().into_iter().enumerate() {
            let line = line.as_array().unwrap();
            let text = line[0].as_string().unwrap().to_string();
            // annotations
            let mut cursor = None;
            let mut selection = None;
            for annotation in line.iter().skip(1).map(|a| a.as_array().unwrap()) {
                match annotation[0].as_string().unwrap() {
                    "cursor" => {
                        cursor = Some(annotation[1].as_u64().unwrap());
                    },
                    "sel" => {
                        selection = Some((annotation[1].as_u64().unwrap(), annotation[2].as_u64().unwrap()));
                    }, _ => () // ignore unknown annotations
                }
            }
            let renderer = LineRenderer::new(renderer, &text);
            self.cache.insert(i as u64+first, Line { text: text, cursor: cursor, selection: selection, renderer: renderer });
        }
    }

    pub fn scroll_to(&mut self, line: u64, _column: u64) {
        let min = |a,b| if a > b { b } else { a };
        let max = |a,b| if a < b { b } else { a };
        self.top = max(0., min(self.top, line as f64 - 2.)); // scroll up
        self.top = min(self.n_lines as f64, max(self.top, line as f64 - self.height + 1. + 2.)); // scroll dn
    }

    pub fn scroll(&mut self, delta_y: f64) {
        let y = self.top + delta_y;
        let max = self.n_lines as f64 - self.height;
        if y > max { self.top = max }
        if self.top < 0. {  self.top = 0. }
    }

    pub fn get_lines(&self) -> Vec<(f32, &Line)> {
        self.get_line_pos().into_iter().filter_map(|(pos,i)| self.get_line(i).map(|x| (pos,x))).collect()
    }

    // Return: Vec<(line_pos, line_id)>
    pub fn get_line_pos(&self) -> Vec<(f32, u64)> {
        (self.top as u64 .. (self.top + self.height).ceil() as u64)
            .map(|i| ((self.height - i as f64 + self.top - 0.5) as f32 * LINE_HEIGHT, i)
            ).collect()
    }

    pub fn get_line_col(&self, px: i32, py: i32) -> (u64,u64) {
        let line = self.get_line_pos().into_iter().min_by_key(|&(y,_)| (y as i32 - py).abs()).unwrap().1;
        let column = if let Some(line) = self.get_line(line) {
            line.renderer.char_pos_x.iter().enumerate().min_by_key(|&(_,x)| {
                (*x as i32 - px + LEFT_MARGIN as i32).abs()
            }).unwrap().0 as u64
        } else { // after the text
            0
        };
        (line, column)
    }

    fn get_line(&self, n: u64) -> Option<&Line> {
        if n >= self.n_lines {
            None
        } else {
            Some(self.cache.get(&n).unwrap_or(&self.placeholder_line))
        }
    }

    pub fn set_size(&mut self, _w: u32, h: u32) {
        self.height = h as f64 / LINE_HEIGHT as f64;
    }
}

pub struct TextRenderer {
    cursor: Primitive,
    line_bg: Primitive,
    left_margin: f32,
}

impl TextRenderer {
    pub fn new(renderer: &Renderer, left_margin: f32) -> TextRenderer {
        let cursor = Primitive::new_line(&renderer, (0.,-10.), (0.,10.), [0.,0.,0.,1.]);
        let line_bg = Primitive::new_rect(&renderer, (0., -10.), (2000., 10.), [1.,1.,0.7,1.]);

        TextRenderer { cursor: cursor, line_bg: line_bg, left_margin: left_margin }
    }

    pub fn draw_line(&self, target: &mut Target, line: &Line, (px, py): (f32, f32)) {
        let offset = |pos| {
            let ch_pos_x = &line.renderer.char_pos_x;
            ch_pos_x[::std::cmp::min(pos as usize, ch_pos_x.len() - 1)]
        };

        if let Some(pos) = line.cursor {
            self.line_bg.draw(target, (px, py)).unwrap();
            self.cursor.draw(target, (offset(pos) + px, py)).unwrap();
        }

        if let Some(sel) = line.selection {
            let selection_bg = Primitive::new_rect(&target.renderer,
                (offset(sel.0) as f32 + px, -10.),
                (offset(sel.1) as f32 + px, 10.),
                [0.5,0.5,1.,1.]);
            selection_bg.draw(target, (0.,py)).unwrap();
        }

        line.renderer.draw(target, px, py);
    }

    pub fn draw(&self, target: &mut Target, lines: &[(f32,&Line)], top: f64, height: f64, n_lines: u64) {
        for &(y, line) in lines {
            self.draw_line(target, &line, (self.left_margin, y));
        }

        // draw scrollbar
        let dims = target.get_dimensions();
        let (w, h) = (dims.0 as f32, dims.1 as f32);
        let (rel_y, rel_h) = (top / n_lines as f64, height / n_lines as f64);
        let scrollbar = Primitive::new_rect(&target.renderer,
            (w - 20., h - rel_y as f32 * h), (w, h - (rel_y + rel_h) as f32 * h),
            [0.5,0.5,0.5,1.]);
        scrollbar.draw(target, (0.,0.)).unwrap();
    }
}
<|endoftext|>


<commit_before>use serde_json;
use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;

#[derive(Deserialize, Debug)]
pub struct User {
    pub name: Option<String>,
    pub irc: Option<String>,
    pub irc_channels: Vec<String>,
    pub show_avatar: bool,
    pub email: Option<String>,
    pub discourse: Option<String>,
    pub reddit: Option<String>,
    pub twitter: Option<String>,
    pub blog: Option<String>,
    pub website: Option<String>,
    pub notes: Option<String>,
}

impl User {
    pub fn lookup(name: &str) -> Result<User, serde_json::Error> {
        let path = {
            let mut path = PathBuf::from("rustaceans.org/data");
            path.push(name);
            path.set_extension("json");
            path
        };
        let reader = BufReader::new(File::open(path)?);
        let user = serde_json::from_reader(reader)?;
        Ok(user)
    }
}

#[test]
fn smoke() {
    const DATA: &'static str = r#"
        {
            "name": "Bors",
            "show_avatar": true,
            "irc": "bors",
            "irc_channels": ["rust", "rust-bots"],
            "website": "http://rust-lang.org/"
        }
    "#;
    serde_json::from_str(DATA).unwrap();
}
<commit_msg>Ignore empty fields<commit_after>use serde_json;
use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;

#[derive(Deserialize, Debug)]
pub struct User {
    // NOTE: when changing these fields, be sure to update
    // `.remove_empty_strings()` below
    pub name: Option<String>,
    pub irc: Option<String>,
    pub irc_channels: Vec<String>,
    pub show_avatar: bool,
    pub email: Option<String>,
    pub discourse: Option<String>,
    pub reddit: Option<String>,
    pub twitter: Option<String>,
    pub blog: Option<String>,
    pub website: Option<String>,
    pub notes: Option<String>,
}

impl User {
    pub fn lookup(name: &str) -> Result<User, serde_json::Error> {
        let path = {
            let mut path = PathBuf::from("rustaceans.org/data");
            path.push(name);
            path.set_extension("json");
            path
        };
        let reader = BufReader::new(File::open(path)?);
        let mut user: User = serde_json::from_reader(reader)?;
        user.remove_empty_strings();
        Ok(user)
    }

    /// Some users use empty strings to mean "not applicable", instead of using
    /// `null` or omitting the field as they should be doing. We fix up their
    /// carelessness here.
    fn remove_empty_strings(&mut self) {
        macro_rules! fixup {
            ($self_:ident, $($field:ident)*) => {
                $(
                    // If the field is just whitespace, replace it with `None`
                    // This boolean dance is needed to satisfy borrowck
                    let should_replace = match $self_.$field {
                        Some(ref s) if is_whitespace(s) => true,
                        _ => false,
                    };
                    if should_replace {
                        $self_.$field = None;
                    }
                )*
            }
        }
        fixup!(self, name irc email discourse reddit twitter blog website notes);
    }
}

fn is_whitespace(s: &str) -> bool {
    s.chars().all(char::is_whitespace)
}

#[test]
fn smoke() {
    const DATA: &'static str = r#"
        {
            "name": "Bors",
            "show_avatar": true,
            "irc": "bors",
            "irc_channels": ["rust", "rust-bots"],
            "website": "http://rust-lang.org/"
        }
    "#;
    serde_json::from_str(DATA).unwrap();
}
<|endoftext|>


<commit_before>
//! Various utilities for rendering and resource management

pub mod graphics {
    //! Wrappers for unsafe OpenGL calls

    use gl;
    use gl::types::*;
    use color::Color;

    /// Sets the opengl viewport
    pub fn viewport(x: u32, y: u32, width: u32, height: u32) {
        unsafe {
            gl::Viewport(x as GLint, y as GLint, width as GLsizei, height as GLsizei);
        }
    }

    /// Prints all OpenGL errors
    pub fn print_errors() {
        unsafe {
            while let Some(error) = get_error_message(gl::GetError()) {
                println!("OpenGL error: {}", error);
            }
        }
    }

    /// Retrieves the strign asscociated with the given OpenGL error. Returns None
    /// if there if no error occured.
    pub fn get_error_message(error: GLenum) -> Option<String> {
        let value = match error {
            gl::INVALID_VALUE                   => "Invalid value",
            gl::INVALID_ENUM                    => "Invalid enum",
            gl::INVALID_OPERATION               => "Invalid operation",
            gl::INVALID_FRAMEBUFFER_OPERATION   => "Invalid framebuffer operation",
            gl::OUT_OF_MEMORY                   => "Out of memory",

            gl::NO_ERROR                        => return None,
            _                                   => return Some(format!("Invalid error code: {:x}", error)),
        };
        Some(String::from(value))
    }

    /// Clears the currently bound framebuffer to the given color. If no color is specified
    /// only the backbuffer is cleared
    pub fn clear(color: Option<Color>, depth: bool, stencil: bool) {
        unsafe {
            if let Some(color) = color {
                gl::ClearColor(color.r, color.g, color.b, color.a);
            }
            let mut mask = 0;
            if color.is_some() { mask |= gl::COLOR_BUFFER_BIT }
            if depth           { mask |= gl::DEPTH_BUFFER_BIT }
            if stencil         { mask |= gl::STENCIL_BUFFER_BIT }
            gl::Clear(mask);
        }
    }

    /// Toggles depth testing. This only has an effect if the currently bound framebuffer
    /// has a depthbuffer (The backbuffer allways has a depthbuffer).
    pub fn set_depth_testing(enabled: bool) {
        unsafe {
            if enabled {
                gl::Enable(gl::DEPTH_TEST);
            } else {
                gl::Disable(gl::DEPTH_TEST);
            }
        }
    }

    /// If passed `Some` enables the given blend settings, if passed `None` disables
    /// blending
    pub fn set_blending(blending: Option<BlendSettings>) {
        unsafe {
            if let Some(ref settings) = blending {
                settings.enable();
            } else {
                gl::Disable(gl::BLEND);
            }
        }
    }

    /// Settings used to define OpenGL blend state. You should create a pair of settings
    /// for every operation which uses blending, and apply those settings before rendering.
    /// Blending can be enabled either through
    /// [`enable()`](struct.BlendSettings.html#method.enable)
    /// or
    /// [`graphics::set_blending(Some(my_settings))`](fn.set_blending.html)
    /// and can be disabled wtih
    /// [`graphics::set_blending(None)`](fn.set_blending.html).
    ///
    /// Note that this struct implements `Default`, so default blend settings can be retrieved
    /// with `BlendSettings::default()`.
    #[derive(Debug, Clone, Copy)]
    pub struct BlendSettings {
        pub src_color: BlendFactor,
        pub src_alpha: BlendFactor,
        pub dst_color: BlendFactor,
        pub dst_alpha: BlendFactor,
        pub function: BlendFunction,
    }
    const DEFAULT_BLEND_SETTINGS: BlendSettings = BlendSettings {
        src_color: BlendFactor::SrcAlpha,
        dst_color: BlendFactor::OneMinusSrcAlpha,
        src_alpha: BlendFactor::One,
        dst_alpha: BlendFactor::Zero,
        function: BlendFunction::Add,
    };
    impl BlendSettings {
        /// Enables blending, and uses these blend settings
        pub fn enable(&self) {
            unsafe {
                gl::Enable(gl::BLEND);
                gl::BlendFuncSeparate(self.src_color as GLenum,
                                      self.dst_color as GLenum,
                                      self.src_alpha as GLenum,
                                      self.dst_alpha as GLenum);
                gl::BlendEquation(self.function as GLenum);
            }
        }
    }
    impl Default for BlendSettings {
        fn default() -> BlendSettings {
            DEFAULT_BLEND_SETTINGS
        }
    }

    /// OpenGL blend functions
    #[repr(u32)] // GLenum is u32
    #[derive(Copy, Clone, Debug)]
    pub enum BlendFactor {
        Zero                    = gl::ZERO,
        One                     = gl::ONE,
        SrcColor                = gl::SRC_COLOR,
        OneMinusSrcColor        = gl::ONE_MINUS_SRC_COLOR,
        DstColor                = gl::DST_COLOR,
        OneMinusDstColor        = gl::ONE_MINUS_DST_COLOR,
        SrcAlpha                = gl::SRC_ALPHA,
        OneMinusSrcAlpha        = gl::ONE_MINUS_SRC_ALPHA,
        DstAlpha                = gl::DST_ALPHA,
        OneMinusDstAlpha        = gl::ONE_MINUS_DST_ALPHA,
        ConstantColor           = gl::CONSTANT_COLOR,
        OneMinusConstantColor   = gl::ONE_MINUS_CONSTANT_COLOR,
        ConstantAlpha           = gl::CONSTANT_ALPHA,
        OneMinusConstantAlpha   = gl::ONE_MINUS_CONSTANT_ALPHA,
    }
    /// OpenGL blend equations
    #[repr(u32)] // GLenum is u32
    #[derive(Copy, Clone, Debug)]
    pub enum BlendFunction {
        /// `Src + Dst`
        Add             = gl::FUNC_ADD,
        /// `Src - Dst`
        Subtract        = gl::FUNC_SUBTRACT,
        /// `Dst - Src`
        ReverseSubtract = gl::FUNC_REVERSE_SUBTRACT,
        /// `min(Dst, Src)`
        Min             = gl::MIN,
        /// `max(Dst, Src)`
        Max             = gl::MAX,
    }
}

pub mod loading {
    //! Utilities for loading/reloading files

    use std::time::SystemTime;
    use std::fs;
    use std::io;
    use std::path::{PathBuf, Path};
    use std::collections::HashMap;

    /// A utility to execute some action when a file has been changed. Files are checked by
    /// periodically calling [`check(...)`](fn.modified_since.html) inside e.g. the main game
    /// loop.
    pub struct ResourceRefresher {
        last_load_times: HashMap<PathBuf, SystemTime>,
    }

    impl ResourceRefresher {
        pub fn new() -> ResourceRefresher {
            ResourceRefresher {
                last_load_times: HashMap::new(),
            }
        }

        /// Returns true if the given file has been modified since the last call to this function.
        /// If an error occurs while checking if the file has been modified this function prints a
        /// error and returns `false`.
        ///
        /// # Example
        /// ```rust,ignore
        /// use util::loading::ResourceRefresher;
        ///
        /// let mut refresher = ResourceRefresher::new();
        ///
        /// // In main loop
        /// if refresher.check("assets/basic.glsl") {
        ///     // Reload shader
        /// }
        /// ```
        pub fn check<P>(&mut self, path: P) -> bool where P: AsRef<Path> {
            let changed = {
                let key = path.as_ref().to_path_buf();
                let load_time = self.last_load_times.entry(key).or_insert(SystemTime::now());

                match modified_since(path.as_ref(), *load_time) {
                    Ok(value) => value,
                    Err(err) => {
                        println!("Failed to check \"{}\" for modification: {}", path.as_ref().to_string_lossy(), err);
                        false
                    }
                }
            };
            if changed {
                let key = path.as_ref().to_path_buf();
                self.last_load_times.insert(key, SystemTime::now());
            }
            changed
        }
    }

    /// Checks if the given file has been modified since the given time.
    pub fn modified_since(path: &Path, last_time: SystemTime) -> io::Result<bool> {
        let metadata = fs::metadata(&path)?;
        let last_modified = metadata.modified()?;

        if let Err(_) = last_time.duration_since(last_modified) {
            return Ok(true);
        } else {
            return Ok(false);
        }
    }
}

<commit_msg>Added culling utilities<commit_after>
//! Various utilities for rendering and resource management

pub mod graphics {
    //! Wrappers for unsafe OpenGL calls

    use gl;
    use gl::types::*;
    use color::Color;

    /// Sets the opengl viewport
    pub fn viewport(x: u32, y: u32, width: u32, height: u32) {
        unsafe {
            gl::Viewport(x as GLint, y as GLint, width as GLsizei, height as GLsizei);
        }
    }

    /// Prints all OpenGL errors
    pub fn print_errors() {
        unsafe {
            while let Some(error) = get_error_message(gl::GetError()) {
                println!("OpenGL error: {}", error);
            }
        }
    }

    /// Retrieves the strign asscociated with the given OpenGL error. Returns None
    /// if there if no error occured.
    pub fn get_error_message(error: GLenum) -> Option<String> {
        let value = match error {
            gl::INVALID_VALUE                   => "Invalid value",
            gl::INVALID_ENUM                    => "Invalid enum",
            gl::INVALID_OPERATION               => "Invalid operation",
            gl::INVALID_FRAMEBUFFER_OPERATION   => "Invalid framebuffer operation",
            gl::OUT_OF_MEMORY                   => "Out of memory",

            gl::NO_ERROR                        => return None,
            _                                   => return Some(format!("Invalid error code: {:x}", error)),
        };
        Some(String::from(value))
    }

    /// Sets which side of a face to treat as the front face and which side of a face to cull. If
    /// `None` is passed this disables culling.
    ///
    /// For simplicity, you can simply call `graphics::set_culling(Some(Default::default()))`,
    /// which will set the winding order to counter-clockwise and cull-face to the back face.
    pub fn set_culling(mode: Option<(WindingOrder, FaceSide)>) {
        unsafe { match mode {
            Some((winding_order, face_side)) => {
                gl::Enable(gl::CULL_FACE);
                match winding_order {
                    WindingOrder::Clockwise => gl::FrontFace(gl::CW),
                    WindingOrder::CounterClockwise => gl::FrontFace(gl::CCW),
                }
                match face_side {
                    FaceSide::Front => gl::CullFace(gl::FRONT),
                    FaceSide::Back => gl::CullFace(gl::BACK),
                }
            },
            None => {
                gl::Disable(gl::CULL_FACE);
            },
        } }
    }

    #[derive(Debug, Copy, Clone)]
    pub enum WindingOrder {
        Clockwise, CounterClockwise,
    }
    #[derive(Debug, Copy, Clone)]
    pub enum FaceSide {
        Front, Back
    }

    impl Default for WindingOrder {
        /// The default winding order is counter-clockwise.
        fn default() -> WindingOrder { WindingOrder::CounterClockwise }
    }
    impl Default for FaceSide {
        /// The default face side is back, as this is the face you want to cull by default.
        fn default() -> FaceSide { FaceSide::Back }
    }

    /// Clears the currently bound framebuffer to the given color. If no color is specified
    /// only the backbuffer is cleared
    pub fn clear(color: Option<Color>, depth: bool, stencil: bool) {
        unsafe {
            if let Some(color) = color {
                gl::ClearColor(color.r, color.g, color.b, color.a);
            }
            let mut mask = 0;
            if color.is_some() { mask |= gl::COLOR_BUFFER_BIT }
            if depth           { mask |= gl::DEPTH_BUFFER_BIT }
            if stencil         { mask |= gl::STENCIL_BUFFER_BIT }
            gl::Clear(mask);
        }
    }

    /// Toggles depth testing. This only has an effect if the currently bound framebuffer
    /// has a depthbuffer (The backbuffer allways has a depthbuffer).
    pub fn set_depth_testing(enabled: bool) {
        unsafe {
            if enabled {
                gl::Enable(gl::DEPTH_TEST);
            } else {
                gl::Disable(gl::DEPTH_TEST);
            }
        }
    }

    /// If passed `Some` enables the given blend settings, if passed `None` disables
    /// blending
    pub fn set_blending(blending: Option<BlendSettings>) {
        unsafe {
            if let Some(ref settings) = blending {
                settings.enable();
            } else {
                gl::Disable(gl::BLEND);
            }
        }
    }

    /// Settings used to define OpenGL blend state. You should create a pair of settings
    /// for every operation which uses blending, and apply those settings before rendering.
    /// Blending can be enabled either through
    /// [`enable()`](struct.BlendSettings.html#method.enable)
    /// or
    /// [`graphics::set_blending(Some(my_settings))`](fn.set_blending.html)
    /// and can be disabled wtih
    /// [`graphics::set_blending(None)`](fn.set_blending.html).
    ///
    /// Note that this struct implements `Default`, so default blend settings can be retrieved
    /// with `BlendSettings::default()`.
    #[derive(Debug, Clone, Copy)]
    pub struct BlendSettings {
        pub src_color: BlendFactor,
        pub src_alpha: BlendFactor,
        pub dst_color: BlendFactor,
        pub dst_alpha: BlendFactor,
        pub function: BlendFunction,
    }
    const DEFAULT_BLEND_SETTINGS: BlendSettings = BlendSettings {
        src_color: BlendFactor::SrcAlpha,
        dst_color: BlendFactor::OneMinusSrcAlpha,
        src_alpha: BlendFactor::One,
        dst_alpha: BlendFactor::Zero,
        function: BlendFunction::Add,
    };
    impl BlendSettings {
        /// Enables blending, and uses these blend settings
        pub fn enable(&self) {
            unsafe {
                gl::Enable(gl::BLEND);
                gl::BlendFuncSeparate(self.src_color as GLenum,
                                      self.dst_color as GLenum,
                                      self.src_alpha as GLenum,
                                      self.dst_alpha as GLenum);
                gl::BlendEquation(self.function as GLenum);
            }
        }
    }
    impl Default for BlendSettings {
        fn default() -> BlendSettings {
            DEFAULT_BLEND_SETTINGS
        }
    }

    /// OpenGL blend functions
    #[repr(u32)] // GLenum is u32
    #[derive(Copy, Clone, Debug)]
    pub enum BlendFactor {
        Zero                    = gl::ZERO,
        One                     = gl::ONE,
        SrcColor                = gl::SRC_COLOR,
        OneMinusSrcColor        = gl::ONE_MINUS_SRC_COLOR,
        DstColor                = gl::DST_COLOR,
        OneMinusDstColor        = gl::ONE_MINUS_DST_COLOR,
        SrcAlpha                = gl::SRC_ALPHA,
        OneMinusSrcAlpha        = gl::ONE_MINUS_SRC_ALPHA,
        DstAlpha                = gl::DST_ALPHA,
        OneMinusDstAlpha        = gl::ONE_MINUS_DST_ALPHA,
        ConstantColor           = gl::CONSTANT_COLOR,
        OneMinusConstantColor   = gl::ONE_MINUS_CONSTANT_COLOR,
        ConstantAlpha           = gl::CONSTANT_ALPHA,
        OneMinusConstantAlpha   = gl::ONE_MINUS_CONSTANT_ALPHA,
    }
    /// OpenGL blend equations
    #[repr(u32)] // GLenum is u32
    #[derive(Copy, Clone, Debug)]
    pub enum BlendFunction {
        /// `Src + Dst`
        Add             = gl::FUNC_ADD,
        /// `Src - Dst`
        Subtract        = gl::FUNC_SUBTRACT,
        /// `Dst - Src`
        ReverseSubtract = gl::FUNC_REVERSE_SUBTRACT,
        /// `min(Dst, Src)`
        Min             = gl::MIN,
        /// `max(Dst, Src)`
        Max             = gl::MAX,
    }
}

pub mod loading {
    //! Utilities for loading/reloading files

    use std::time::SystemTime;
    use std::fs;
    use std::io;
    use std::path::{PathBuf, Path};
    use std::collections::HashMap;

    /// A utility to execute some action when a file has been changed. Files are checked by
    /// periodically calling [`check(...)`](fn.modified_since.html) inside e.g. the main game
    /// loop.
    pub struct ResourceRefresher {
        last_load_times: HashMap<PathBuf, SystemTime>,
    }

    impl ResourceRefresher {
        pub fn new() -> ResourceRefresher {
            ResourceRefresher {
                last_load_times: HashMap::new(),
            }
        }

        /// Returns true if the given file has been modified since the last call to this function.
        /// If an error occurs while checking if the file has been modified this function prints a
        /// error and returns `false`.
        ///
        /// # Example
        /// ```rust,ignore
        /// use util::loading::ResourceRefresher;
        ///
        /// let mut refresher = ResourceRefresher::new();
        ///
        /// // In main loop
        /// if refresher.check("assets/basic.glsl") {
        ///     // Reload shader
        /// }
        /// ```
        pub fn check<P>(&mut self, path: P) -> bool where P: AsRef<Path> {
            let changed = {
                let key = path.as_ref().to_path_buf();
                let load_time = self.last_load_times.entry(key).or_insert(SystemTime::now());

                match modified_since(path.as_ref(), *load_time) {
                    Ok(value) => value,
                    Err(err) => {
                        println!("Failed to check \"{}\" for modification: {}", path.as_ref().to_string_lossy(), err);
                        false
                    }
                }
            };
            if changed {
                let key = path.as_ref().to_path_buf();
                self.last_load_times.insert(key, SystemTime::now());
            }
            changed
        }
    }

    /// Checks if the given file has been modified since the given time.
    pub fn modified_since(path: &Path, last_time: SystemTime) -> io::Result<bool> {
        let metadata = fs::metadata(&path)?;
        let last_modified = metadata.modified()?;

        if let Err(_) = last_time.duration_since(last_modified) {
            return Ok(true);
        } else {
            return Ok(false);
        }
    }
}

<|endoftext|>