<commit_before>//! Song analysis module.
//!
//! Contains various functions to extract meaningful features from a `Song`,
//! e.g. tempo features, spectral features, etc.
#[cfg(feature = "aubio-lib")]
extern crate aubio_lib;

use aubio_rs::{bin_to_freq, silence_detection, OnsetMode, PVoc, SpecDesc, SpecShape, Tempo};

use super::utils::{mean, number_crossings};

struct ZeroCrossingRateDesc {
    values: Vec<u32>,
    number_samples: usize,
}

impl ZeroCrossingRateDesc {
    const HOP_SIZE: usize = 1024;

    pub fn new() -> Self {
        ZeroCrossingRateDesc {
            values: Vec::new(),
            number_samples: 0,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.values.push(number_crossings(chunk));
        self.number_samples += chunk.len();
    }

    pub fn get_value(&mut self) -> f32 {
        (self.values.iter().sum::<u32>()) as f32 / self.number_samples as f32
    }
}

// TODO write proper doc
struct TempoDesc {
    aubio_obj: Tempo,
}

impl TempoDesc {
    const WINDOW_SIZE: usize = 1024;
    const HOP_SIZE: usize = TempoDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        TempoDesc {
            aubio_obj: Tempo::new(
                OnsetMode::SpecDiff,
                TempoDesc::WINDOW_SIZE,
                TempoDesc::HOP_SIZE,
                sample_rate,
            )
            .unwrap(),
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.aubio_obj.do_result(chunk).unwrap();
    }

    /**
     * Compute score related to tempo.
     * Right now, basically returns the song's BPM.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        self.aubio_obj.get_bpm()
    }
}

struct SpectralRollOffDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

struct SpectralCentroidDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

impl SpectralRollOffDesc {
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralRollOffDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralRollOffDesc {
            aubio_obj: SpecDesc::new(SpecShape::Rolloff, SpectralRollOffDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralRollOffDesc::WINDOW_SIZE,
                SpectralRollOffDesc::HOP_SIZE,
            )
            .unwrap(),
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralRollOffDesc::WINDOW_SIZE + 2];

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let bin = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        let freq = bin_to_freq(
            bin,
            self.sample_rate as f32,
            SpectralRollOffDesc::WINDOW_SIZE as f32,
        );
        self.values.push(freq);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

impl SpectralCentroidDesc {
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralCentroidDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralCentroidDesc {
            aubio_obj: SpecDesc::new(SpecShape::Centroid, SpectralCentroidDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralCentroidDesc::WINDOW_SIZE,
                SpectralCentroidDesc::HOP_SIZE,
            )
            .unwrap(),
            // TODO vec with capacity?
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralCentroidDesc::WINDOW_SIZE + 2];
        // If silence, centroid will be off, so skip instead
        if silence_detection(chunk, -60.0) {
            return;
        }

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let bin = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        let freq = bin_to_freq(
            bin,
            self.sample_rate as f32,
            SpectralCentroidDesc::WINDOW_SIZE as f32,
        );
        self.values.push(freq);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

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

    #[test]
    fn test_zcr() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut zcr_desc = ZeroCrossingRateDesc::new();
        for chunk in song.sample_array.chunks(ZeroCrossingRateDesc::HOP_SIZE) {
            zcr_desc.do_(&chunk);
        }
        assert!(0.001 > (0.075 - zcr_desc.get_value()).abs());
    }

    #[test]
    fn test_tempo() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut tempo_desc = TempoDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(TempoDesc::HOP_SIZE) {
            tempo_desc.do_(&chunk);
        }
        assert!(0.01 > (142.38 - tempo_desc.get_value()).abs());
    }

    #[test]
    fn test_roll_off() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut roll_off_desc = SpectralRollOffDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralRollOffDesc::HOP_SIZE) {
            roll_off_desc.do_(&chunk);
        }
        assert!(0.01 > (2026.69 - roll_off_desc.get_value()).abs());
    }

    #[test]
    fn test_centroid() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut centroid_desc = SpectralCentroidDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralCentroidDesc::HOP_SIZE) {
            centroid_desc.do_(&chunk);
        }
        assert!(0.01 > (1236.39 - centroid_desc.get_value()).abs());
    }
}
<commit_msg>Add spectral flatness<commit_after>//! Song analysis module.
//!
//! Contains various functions to extract meaningful features from a `Song`,
//! e.g. tempo features, spectral features, etc.
#[cfg(feature = "aubio-lib")]
extern crate aubio_lib;

use aubio_rs::{bin_to_freq, silence_detection, OnsetMode, PVoc, SpecDesc, SpecShape, Tempo};

use super::utils::{mean, number_crossings};

struct ZeroCrossingRateDesc {
    values: Vec<u32>,
    number_samples: usize,
}

impl ZeroCrossingRateDesc {
    const HOP_SIZE: usize = 1024;

    pub fn new() -> Self {
        ZeroCrossingRateDesc {
            values: Vec::new(),
            number_samples: 0,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.values.push(number_crossings(chunk));
        self.number_samples += chunk.len();
    }

    pub fn get_value(&mut self) -> f32 {
        (self.values.iter().sum::<u32>()) as f32 / self.number_samples as f32
    }
}

// TODO write proper doc
struct TempoDesc {
    aubio_obj: Tempo,
}

impl TempoDesc {
    const WINDOW_SIZE: usize = 1024;
    const HOP_SIZE: usize = TempoDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        TempoDesc {
            aubio_obj: Tempo::new(
                OnsetMode::SpecDiff,
                TempoDesc::WINDOW_SIZE,
                TempoDesc::HOP_SIZE,
                sample_rate,
            )
            .unwrap(),
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.aubio_obj.do_result(chunk).unwrap();
    }

    /**
     * Compute score related to tempo.
     * Right now, basically returns the song's BPM.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        self.aubio_obj.get_bpm()
    }
}

struct SpectralFlatnessDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

impl SpectralFlatnessDesc{
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralFlatnessDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralFlatnessDesc {
            aubio_obj: SpecDesc::new(SpecShape::Kurtosis, SpectralFlatnessDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralFlatnessDesc::WINDOW_SIZE,
                SpectralFlatnessDesc::HOP_SIZE,
            )
            .unwrap(),
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralFlatnessDesc::WINDOW_SIZE + 2];

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let flatness = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        self.values.push(flatness);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    // TODO do we really want the mean there?
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

struct SpectralRollOffDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

struct SpectralCentroidDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

impl SpectralRollOffDesc {
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralRollOffDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralRollOffDesc {
            aubio_obj: SpecDesc::new(SpecShape::Rolloff, SpectralRollOffDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralRollOffDesc::WINDOW_SIZE,
                SpectralRollOffDesc::HOP_SIZE,
            )
            .unwrap(),
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralRollOffDesc::WINDOW_SIZE + 2];

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let bin = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        let freq = bin_to_freq(
            bin,
            self.sample_rate as f32,
            SpectralRollOffDesc::WINDOW_SIZE as f32,
        );
        self.values.push(freq);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

impl SpectralCentroidDesc {
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralCentroidDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralCentroidDesc {
            aubio_obj: SpecDesc::new(SpecShape::Centroid, SpectralCentroidDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralCentroidDesc::WINDOW_SIZE,
                SpectralCentroidDesc::HOP_SIZE,
            )
            .unwrap(),
            // TODO vec with capacity?
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralCentroidDesc::WINDOW_SIZE + 2];
        // If silence, centroid will be off, so skip instead
        if silence_detection(chunk, -60.0) {
            return;
        }

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let bin = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        let freq = bin_to_freq(
            bin,
            self.sample_rate as f32,
            SpectralCentroidDesc::WINDOW_SIZE as f32,
        );
        self.values.push(freq);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

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

    #[test]
    fn test_zcr() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut zcr_desc = ZeroCrossingRateDesc::new();
        for chunk in song.sample_array.chunks(ZeroCrossingRateDesc::HOP_SIZE) {
            zcr_desc.do_(&chunk);
        }
        assert!(0.001 > (0.075 - zcr_desc.get_value()).abs());
    }

    #[test]
    fn test_tempo() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut tempo_desc = TempoDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(TempoDesc::HOP_SIZE) {
            tempo_desc.do_(&chunk);
        }
        assert!(0.01 > (142.38 - tempo_desc.get_value()).abs());
    }

    #[test]
    fn test_flatness() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut flatness_desc = SpectralFlatnessDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralFlatnessDesc::HOP_SIZE) {
            flatness_desc.do_(&chunk);
        }
        assert!(0.01 > (12.74 - flatness_desc.get_value()).abs());
    }

    #[test]
    fn test_roll_off() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut roll_off_desc = SpectralRollOffDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralRollOffDesc::HOP_SIZE) {
            roll_off_desc.do_(&chunk);
        }
        assert!(0.01 > (2026.69 - roll_off_desc.get_value()).abs());
    }

    #[test]
    fn test_centroid() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut centroid_desc = SpectralCentroidDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralCentroidDesc::HOP_SIZE) {
            centroid_desc.do_(&chunk);
        }
        assert!(0.01 > (1236.39 - centroid_desc.get_value()).abs());
    }
}
<|endoftext|>


<commit_before>//! Defines the `TimeManager` trait.

use uci::SetOption;
use hash_table::Variation;
use search::*;

/// Describes the remaining time on the clocks.
#[derive(Clone, Debug)]
pub struct RemainingTime {
    /// The remaining time in milliseconds for white.
    pub white_millis: u64,

    /// The remaining time in milliseconds for black.
    pub black_millis: u64,

    /// The number of milliseconds with which white's remaining time
    /// is incremented on each move.
    pub winc_millis: u64,

    /// The number of milliseconds with which black's remaining time
    /// is incremented on each move.
    pub binc_millis: u64,

    /// The number of moves to the next time control.
    ///
    /// Can not be zero.
    pub movestogo: Option<u64>,
}

/// A trait for deciding when the search must be terminated and the
/// best move played.
pub trait TimeManager<T: DeepeningSearch<ReportData = Vec<Variation>>>
    : SetOption {
    /// Creates a new instance.
    ///
    /// * `position` gives the current position.
    ///
    /// * `time` gives the remaining time on the clocks.
    fn new(position: &T::SearchNode, time: &RemainingTime) -> Self;

    /// Returns `true` if the search must be terminated and the best
    /// move played.
    ///
    /// * `search_instance` is a mutable reference to the running
    ///   search instance. The time manager should be careful when
    ///   calling methods on the currently running search instance, so
    ///   as not to disturb its normal working. In particular,
    ///   `start_search` and `try_recv_report` methods must not be
    ///   called, and a `"TERMINATE"` message must not be sent.
    ///
    /// * `report`, when supplied, gives a reference to an incoming
    ///   search progress report. `must_play` will be called exactly
    ///   once for each progress report generated by the search,
    ///   following the order in which the reports have been
    ///   generated.
    fn must_play(&mut self,
                 search_instance: &mut T,
                 report: Option<&SearchReport<Vec<Variation>>>)
                 -> bool;
}
<commit_msg>improve docs<commit_after>//! Defines the `TimeManager` trait.

use uci::SetOption;
use hash_table::Variation;
use search::*;

/// Describes the remaining time on the clocks.
#[derive(Clone, Debug)]
pub struct RemainingTime {
    /// The remaining time in milliseconds for white.
    pub white_millis: u64,

    /// The remaining time in milliseconds for black.
    pub black_millis: u64,

    /// The number of milliseconds with which white's remaining time
    /// is incremented on each move.
    pub winc_millis: u64,

    /// The number of milliseconds with which black's remaining time
    /// is incremented on each move.
    pub binc_millis: u64,

    /// The number of moves to the next time control.
    ///
    /// Can not be zero.
    pub movestogo: Option<u64>,
}

/// A trait for deciding when the search must be terminated and the
/// best move played.
pub trait TimeManager<T: DeepeningSearch<ReportData = Vec<Variation>>>
    : SetOption {
    /// Creates a new instance.
    ///
    /// * `position` gives the current position.
    ///
    /// * `time` gives the remaining time on the clocks.
    fn new(position: &T::SearchNode, time: &RemainingTime) -> Self;

    /// Returns `true` if the search must be terminated and the best
    /// move played.
    ///
    /// * `search_instance` is a mutable reference to the managed
    ///   search instance. The time manager should be careful when
    ///   calling methods on the managed search instance, so as not to
    ///   disturb its normal working. In particular, `start_search`
    ///   and `try_recv_report` methods must not be called, and a
    ///   `"TERMINATE"` message must not be sent.
    ///
    /// * `report`, when supplied, gives a reference to an incoming
    ///   search progress report. `must_play` will be called exactly
    ///   once for each progress report generated by the search,
    ///   following the order in which the reports have been
    ///   generated.
    fn must_play(&mut self,
                 search_instance: &mut T,
                 report: Option<&SearchReport<Vec<Variation>>>)
                 -> bool;
}
<|endoftext|>


<commit_before>//! Convert most of the [Time Strings](http://sqlite.org/lang_datefunc.html) to chrono types.
use chrono;

use std::borrow::Cow;

use self::chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};

use crate::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
use crate::Result;

/// ISO 8601 calendar date without timezone => "YYYY-MM-DD"
impl ToSql for NaiveDate {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        let date_str = self.format("%Y-%m-%d").to_string();
        Ok(ToSqlOutput::from(date_str))
    }
}

/// "YYYY-MM-DD" => ISO 8601 calendar date without timezone.
impl FromSql for NaiveDate {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value
            .as_str()
            .and_then(|s| match NaiveDate::parse_from_str(s, "%Y-%m-%d") {
                Ok(dt) => Ok(dt),
                Err(err) => Err(FromSqlError::Other(Box::new(err))),
            })
    }
}

/// ISO 8601 time without timezone => "HH:MM:SS.SSS"
impl ToSql for NaiveTime {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        let date_str = self.format("%H:%M:%S%.f").to_string();
        Ok(ToSqlOutput::from(date_str))
    }
}

/// "HH:MM"/"HH:MM:SS"/"HH:MM:SS.SSS" => ISO 8601 time without timezone.
impl FromSql for NaiveTime {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_str().and_then(|s| {
            let fmt = match s.len() {
                5 => "%H:%M",
                8 => "%H:%M:%S",
                _ => "%H:%M:%S%.f",
            };
            match NaiveTime::parse_from_str(s, fmt) {
                Ok(dt) => Ok(dt),
                Err(err) => Err(FromSqlError::Other(Box::new(err))),
            }
        })
    }
}

/// ISO 8601 combined date and time without timezone =>
/// "YYYY-MM-DD HH:MM:SS.SSS"
impl ToSql for NaiveDateTime {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        let date_str = self.format("%Y-%m-%dT%H:%M:%S%.f").to_string();
        Ok(ToSqlOutput::from(date_str))
    }
}

/// "YYYY-MM-DD HH:MM:SS"/"YYYY-MM-DD HH:MM:SS.SSS" => ISO 8601 combined date
/// and time without timezone. ("YYYY-MM-DDTHH:MM:SS"/"YYYY-MM-DDTHH:MM:SS.SSS"
/// also supported)
impl FromSql for NaiveDateTime {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_str().and_then(|s| {
            let fmt = if s.len() >= 11 && s.as_bytes()[10] == b'T' {
                "%Y-%m-%dT%H:%M:%S%.f"
            } else {
                "%Y-%m-%d %H:%M:%S%.f"
            };

            match NaiveDateTime::parse_from_str(s, fmt) {
                Ok(dt) => Ok(dt),
                Err(err) => Err(FromSqlError::Other(Box::new(err))),
            }
        })
    }
}

/// Date and time with time zone => UTC RFC3339 timestamp
/// ("YYYY-MM-DDTHH:MM:SS.SSS+00:00").
impl<Tz: TimeZone> ToSql for DateTime<Tz> {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        Ok(ToSqlOutput::from(self.with_timezone(&Utc).to_rfc3339()))
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into `DateTime<Utc>`.
impl FromSql for DateTime<Utc> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        {
            // Try to parse value as rfc3339 first.
            let s = value.as_str()?;

            // If timestamp looks space-separated, make a copy and replace it with 'T'.
            let s = if s.len() >= 11 && s.as_bytes()[10] == b' ' {
                let mut s = s.to_string();
                unsafe {
                    let sbytes = s.as_mut_vec();
                    sbytes[10] = b'T';
                }
                Cow::Owned(s)
            } else {
                Cow::Borrowed(s)
            };

            if let Ok(dt) = DateTime::parse_from_rfc3339(&s) {
                return Ok(dt.with_timezone(&Utc));
            }
        }

        // Couldn't parse as rfc3339 - fall back to NaiveDateTime.
        NaiveDateTime::column_result(value).map(|dt| Utc.from_utc_datetime(&dt))
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into `DateTime<Local>`.
impl FromSql for DateTime<Local> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        let utc_dt = DateTime::<Utc>::column_result(value)?;
        Ok(utc_dt.with_timezone(&Local))
    }
}

#[cfg(test)]
mod test {
    use super::chrono::{
        DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc,
    };
    use crate::{Connection, Result, NO_PARAMS};

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)")
            .unwrap();
        db
    }

    #[test]
    fn test_naive_date() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&date])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("2016-02-23", s);
        let t: NaiveDate = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(date, t);
    }

    #[test]
    fn test_naive_time() {
        let db = checked_memory_handle();
        let time = NaiveTime::from_hms(23, 56, 4);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&time])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("23:56:04", s);
        let v: NaiveTime = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(time, v);
    }

    #[test]
    fn test_naive_date_time() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms(23, 56, 4);
        let dt = NaiveDateTime::new(date, time);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("2016-02-23T23:56:04", s);
        let v: NaiveDateTime = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(dt, v);

        db.execute("UPDATE foo set b = datetime(t)", NO_PARAMS)
            .unwrap(); // "YYYY-MM-DD HH:MM:SS"
        let hms: NaiveDateTime = db
            .query_row("SELECT b FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(dt, hms);
    }

    #[test]
    fn test_date_time_utc() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let utc = Utc.from_utc_datetime(&dt);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("2016-02-23T23:56:04.789+00:00", s);

        let v1: DateTime<Utc> = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(utc, v1);

        let v2: DateTime<Utc> = db
            .query_row("SELECT '2016-02-23 23:56:04.789'", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(utc, v2);

        let v3: DateTime<Utc> = db
            .query_row("SELECT '2016-02-23 23:56:04'", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(utc - Duration::milliseconds(789), v3);

        let v4: DateTime<Utc> = db
            .query_row("SELECT '2016-02-23 23:56:04.789+00:00'", NO_PARAMS, |r| {
                r.get(0)
            })
            .unwrap();
        assert_eq!(utc, v4);
    }

    #[test]
    fn test_date_time_local() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let local = Local.from_local_datetime(&dt).single().unwrap();

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&local])
            .unwrap();

        // Stored string should be in UTC
        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert!(s.ends_with("+00:00"));

        let v: DateTime<Local> = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(local, v);
    }

    #[test]
    fn test_sqlite_functions() {
        let db = checked_memory_handle();
        let result: Result<NaiveTime> =
            db.query_row("SELECT CURRENT_TIME", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
        let result: Result<NaiveDate> =
            db.query_row("SELECT CURRENT_DATE", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
        let result: Result<NaiveDateTime> =
            db.query_row("SELECT CURRENT_TIMESTAMP", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
        let result: Result<DateTime<Utc>> =
            db.query_row("SELECT CURRENT_TIMESTAMP", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
    }
}
<commit_msg>[ci skip] Fix rustdoc<commit_after>//! Convert most of the [Time Strings](http://sqlite.org/lang_datefunc.html) to chrono types.
use chrono;

use std::borrow::Cow;

use self::chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};

use crate::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
use crate::Result;

/// ISO 8601 calendar date without timezone => "YYYY-MM-DD"
impl ToSql for NaiveDate {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        let date_str = self.format("%Y-%m-%d").to_string();
        Ok(ToSqlOutput::from(date_str))
    }
}

/// "YYYY-MM-DD" => ISO 8601 calendar date without timezone.
impl FromSql for NaiveDate {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value
            .as_str()
            .and_then(|s| match NaiveDate::parse_from_str(s, "%Y-%m-%d") {
                Ok(dt) => Ok(dt),
                Err(err) => Err(FromSqlError::Other(Box::new(err))),
            })
    }
}

/// ISO 8601 time without timezone => "HH:MM:SS.SSS"
impl ToSql for NaiveTime {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        let date_str = self.format("%H:%M:%S%.f").to_string();
        Ok(ToSqlOutput::from(date_str))
    }
}

/// "HH:MM"/"HH:MM:SS"/"HH:MM:SS.SSS" => ISO 8601 time without timezone.
impl FromSql for NaiveTime {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_str().and_then(|s| {
            let fmt = match s.len() {
                5 => "%H:%M",
                8 => "%H:%M:%S",
                _ => "%H:%M:%S%.f",
            };
            match NaiveTime::parse_from_str(s, fmt) {
                Ok(dt) => Ok(dt),
                Err(err) => Err(FromSqlError::Other(Box::new(err))),
            }
        })
    }
}

/// ISO 8601 combined date and time without timezone =>
/// "YYYY-MM-DDTHH:MM:SS.SSS"
impl ToSql for NaiveDateTime {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        let date_str = self.format("%Y-%m-%dT%H:%M:%S%.f").to_string();
        Ok(ToSqlOutput::from(date_str))
    }
}

/// "YYYY-MM-DD HH:MM:SS"/"YYYY-MM-DD HH:MM:SS.SSS" => ISO 8601 combined date
/// and time without timezone. ("YYYY-MM-DDTHH:MM:SS"/"YYYY-MM-DDTHH:MM:SS.SSS"
/// also supported)
impl FromSql for NaiveDateTime {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_str().and_then(|s| {
            let fmt = if s.len() >= 11 && s.as_bytes()[10] == b'T' {
                "%Y-%m-%dT%H:%M:%S%.f"
            } else {
                "%Y-%m-%d %H:%M:%S%.f"
            };

            match NaiveDateTime::parse_from_str(s, fmt) {
                Ok(dt) => Ok(dt),
                Err(err) => Err(FromSqlError::Other(Box::new(err))),
            }
        })
    }
}

/// Date and time with time zone => UTC RFC3339 timestamp
/// ("YYYY-MM-DDTHH:MM:SS.SSS+00:00").
impl<Tz: TimeZone> ToSql for DateTime<Tz> {
    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
        Ok(ToSqlOutput::from(self.with_timezone(&Utc).to_rfc3339()))
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into `DateTime<Utc>`.
impl FromSql for DateTime<Utc> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        {
            // Try to parse value as rfc3339 first.
            let s = value.as_str()?;

            // If timestamp looks space-separated, make a copy and replace it with 'T'.
            let s = if s.len() >= 11 && s.as_bytes()[10] == b' ' {
                let mut s = s.to_string();
                unsafe {
                    let sbytes = s.as_mut_vec();
                    sbytes[10] = b'T';
                }
                Cow::Owned(s)
            } else {
                Cow::Borrowed(s)
            };

            if let Ok(dt) = DateTime::parse_from_rfc3339(&s) {
                return Ok(dt.with_timezone(&Utc));
            }
        }

        // Couldn't parse as rfc3339 - fall back to NaiveDateTime.
        NaiveDateTime::column_result(value).map(|dt| Utc.from_utc_datetime(&dt))
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into `DateTime<Local>`.
impl FromSql for DateTime<Local> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        let utc_dt = DateTime::<Utc>::column_result(value)?;
        Ok(utc_dt.with_timezone(&Local))
    }
}

#[cfg(test)]
mod test {
    use super::chrono::{
        DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc,
    };
    use crate::{Connection, Result, NO_PARAMS};

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)")
            .unwrap();
        db
    }

    #[test]
    fn test_naive_date() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&date])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("2016-02-23", s);
        let t: NaiveDate = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(date, t);
    }

    #[test]
    fn test_naive_time() {
        let db = checked_memory_handle();
        let time = NaiveTime::from_hms(23, 56, 4);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&time])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("23:56:04", s);
        let v: NaiveTime = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(time, v);
    }

    #[test]
    fn test_naive_date_time() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms(23, 56, 4);
        let dt = NaiveDateTime::new(date, time);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("2016-02-23T23:56:04", s);
        let v: NaiveDateTime = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(dt, v);

        db.execute("UPDATE foo set b = datetime(t)", NO_PARAMS)
            .unwrap(); // "YYYY-MM-DD HH:MM:SS"
        let hms: NaiveDateTime = db
            .query_row("SELECT b FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(dt, hms);
    }

    #[test]
    fn test_date_time_utc() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let utc = Utc.from_utc_datetime(&dt);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc])
            .unwrap();

        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!("2016-02-23T23:56:04.789+00:00", s);

        let v1: DateTime<Utc> = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(utc, v1);

        let v2: DateTime<Utc> = db
            .query_row("SELECT '2016-02-23 23:56:04.789'", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(utc, v2);

        let v3: DateTime<Utc> = db
            .query_row("SELECT '2016-02-23 23:56:04'", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(utc - Duration::milliseconds(789), v3);

        let v4: DateTime<Utc> = db
            .query_row("SELECT '2016-02-23 23:56:04.789+00:00'", NO_PARAMS, |r| {
                r.get(0)
            })
            .unwrap();
        assert_eq!(utc, v4);
    }

    #[test]
    fn test_date_time_local() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let local = Local.from_local_datetime(&dt).single().unwrap();

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&local])
            .unwrap();

        // Stored string should be in UTC
        let s: String = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert!(s.ends_with("+00:00"));

        let v: DateTime<Local> = db
            .query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))
            .unwrap();
        assert_eq!(local, v);
    }

    #[test]
    fn test_sqlite_functions() {
        let db = checked_memory_handle();
        let result: Result<NaiveTime> =
            db.query_row("SELECT CURRENT_TIME", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
        let result: Result<NaiveDate> =
            db.query_row("SELECT CURRENT_DATE", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
        let result: Result<NaiveDateTime> =
            db.query_row("SELECT CURRENT_TIMESTAMP", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
        let result: Result<DateTime<Utc>> =
            db.query_row("SELECT CURRENT_TIMESTAMP", NO_PARAMS, |r| r.get(0));
        assert!(result.is_ok());
    }
}
<|endoftext|>


<commit_before>//! Biology related constants

// http://bionumbers.hms.harvard.edu/search.aspx?task=searchbypop

// Bacteria Escherichia coli
/// µm^3
pub const e_coli_cell_total_volume: f64 = 1.1;
/// µm^3
pub const e_coli_cell_total_volume_min: f64 = 0.44;
/// µm^3
pub const e_coli_cell_total_volume_max: f64 = 1.79;
/// nm
pub const e_coli_outer_membrane_thickness: f64 = 13.0;
/// nm
pub const e_coli_outer_membrane_thickness_min: f64 = 12.0;
/// nm
pub const e_coli_outer_membrane_thickness_max: f64 = 14.0;
/// %
pub const e_coli_volume_occupied_by_water: f64 = 70.0;
/// Unitless
pub const e_coli_number_of_all_rna_per_cell: f64 = 255000.0;
/// Unitless
pub const e_coli_number_of_lipopolysaccharide_per_cell: f64 = 1430000.0;
/// Unitless
pub const e_coli_number_of_lipids_per_cell: f64 = 22000000.0;
/// Unitless
pub const e_coli_number_of_protein_types_to_make_ribosome: f64 = 56.0;
/// Unitless
pub const e_coli_number_of_proteins_in_30s_subunit: f64 = 22.0;
/// Unitless
pub const e_coli_number_of_proteins_in_50s_subunit: f64 = 36.0;
/// fg
pub const e_coli_mass_in_excess_of_displaced_buffer: f64 = 110.0;
/// fg
pub const e_coli_mass_in_excess_of_displaced_buffer_min: f64 = 80.0;
/// fg
pub const e_coli_mass_in_excess_of_displaced_buffer_max: f64 = 140.0;
/// µM
pub const e_coli_total_amount_of_laci_repressor: f64 = 0.01;
/// µM
pub const e_coli_maximal_amount_of_lacz: f64 = 50.0;
/// µM
pub const e_coli_maximal_amount_of_lacy: f64 = 50.0;
/// Molecules / minute
pub const e_coli_velocity_of_allolactose_hydrolysis_by_lacz: f64 = 20_000.0;
/// μM
pub const e_coli_affinity_of_allolactose_and_laci: f64 = 6.0;
/// mM
pub const e_coli_affinity_of_allolactose_and_lacz: f64 = 1.9;
/// µmol / g
pub const e_coli_glutamine_pool_size: f64 = 3.92;
/// µmol / g
pub const e_coli_glutamine_pool_size_min: f64 = 3.75;
/// µmol / g
pub const e_coli_glutamine_pool_size_max: f64 = 4.09;
/// µmol / g
pub const e_coli_glutamate_pool_size: f64 = 100.55;
/// µmol / g
pub const e_coli_glutamate_pool_size_min: f64 = 83.001;
/// µmol / g
pub const e_coli_glutamate_pool_size_max: f64 = 118.09;
/// µmol / g
pub const e_coli_alanine_pool_size: f64 = 6.81;
/// µmol / g
pub const e_coli_alanine_pool_size_min: f64 = 5.102;
/// µmol / g
pub const e_coli_alanine_pool_size_max: f64 = 8.51;
/// µmol / g
pub const e_coli_asparagine_pool_size: f64 = 2.02;
/// µmol / g
pub const e_coli_asparagine_pool_size_min: f64 = 1.56;
/// µmol / g
pub const e_coli_asparagine_pool_size_max: f64 = 2.48;
/// µmol / g
pub const e_coli_aspartate_pool_size: f64 = 6.45;
/// µmol / g
pub const e_coli_aspartate_pool_size_min: f64 = 9.9;
/// µmol / g
pub const e_coli_aspartate_pool_size_max: f64 = 2.91;
/// µmol / g
pub const e_coli_methionine_pool_size: f64 = 0.29;
/// µmol / g
pub const e_coli_methionine_pool_size_min: f64 = 0.22;
/// µmol / g
pub const e_coli_methionine_pool_size_max: f64 = 0.36;
/// µmol / g
pub const e_coli_proline_pool_size: f64 = 1.1;
/// µmol / g
pub const e_coli_proline_pool_size_min: f64 = 0.95;
/// µmol / g
pub const e_coli_proline_pool_size_max: f64 = 1.25;
/// µmol / g
pub const e_coli_threonine_pool_size: f64 = 1.34;
/// µmol / g
pub const e_coli_threonine_pool_size_min: f64 = 1.50;
/// µmol / g
pub const e_coli_threonine_pool_size_max: f64 = 1.18;
/// µmol / g
pub const e_coli_tyrosine_pool_size: f64 = 0.41;
/// µmol / g
pub const e_coli_tyrosine_pool_size_min: f64 = 0.16;
/// µmol / g
pub const e_coli_tyrosine_pool_size_max: f64 = 0.66;
/// µmol / g
pub const e_coli_valine_pool_size: f64 = 2.41;
/// µmol / g
pub const e_coli_valine_pool_size_min: f64 = 2.14;
/// µmol / g
pub const e_coli_valine_pool_size_max: f64 = 2.68;
/// µmol / g
pub const e_coli_carbamoyl_aspartate_pool_size: f64 = 0.84;
/// µmol / g
pub const e_coli_carbamoyl_aspartate_pool_size_min: f64 = 0.56;
/// µmol / g
pub const e_coli_carbamoyl_aspartate_pool_size_max: f64 = 1.12;
/// µmol / g
pub const e_coli_imp_pool_size: f64 = 0.38;
/// µmol / g
pub const e_coli_imp_pool_size_min: f64 = 0.37;
/// µmol / g
pub const e_coli_imp_pool_size_max: f64 = 0.39;
/// %
pub const e_coli_percent_of_cell_total_dry_weight_that_is_lipopolysaccharide: f64 = 3.4;
/// Molecules / cell
pub const e_coli_reca_molecules_per_cell: f64 = 1000;
/// %
pub const e_coli_reca_molecules_per_cell_min: f64 = 800;
/// %
pub const e_coli_reca_molecules_per_cell_max: f64 = 1200;
/// µm^2/sec
pub const e_coli_apparent_diffusion_constant_of_protein_along_dna_segments: f64 = 0.4;
/// µm^2/sec
pub const e_coli_apparent_diffusion_constant_of_protein_along_dna_segments_min: f64 = 0.38;
/// µm^2/sec
pub const e_coli_apparent_diffusion_constant_of_protein_along_dna_segments_max: f64 = 0.42;
<commit_msg>Fix floats<commit_after>//! Biology related constants

// http://bionumbers.hms.harvard.edu/search.aspx?task=searchbypop

// Bacteria Escherichia coli
/// µm^3
pub const e_coli_cell_total_volume: f64 = 1.1;
/// µm^3
pub const e_coli_cell_total_volume_min: f64 = 0.44;
/// µm^3
pub const e_coli_cell_total_volume_max: f64 = 1.79;
/// nm
pub const e_coli_outer_membrane_thickness: f64 = 13.0;
/// nm
pub const e_coli_outer_membrane_thickness_min: f64 = 12.0;
/// nm
pub const e_coli_outer_membrane_thickness_max: f64 = 14.0;
/// %
pub const e_coli_volume_occupied_by_water: f64 = 70.0;
/// Unitless
pub const e_coli_number_of_all_rna_per_cell: f64 = 255000.0;
/// Unitless
pub const e_coli_number_of_lipopolysaccharide_per_cell: f64 = 1430000.0;
/// Unitless
pub const e_coli_number_of_lipids_per_cell: f64 = 22000000.0;
/// Unitless
pub const e_coli_number_of_protein_types_to_make_ribosome: f64 = 56.0;
/// Unitless
pub const e_coli_number_of_proteins_in_30s_subunit: f64 = 22.0;
/// Unitless
pub const e_coli_number_of_proteins_in_50s_subunit: f64 = 36.0;
/// fg
pub const e_coli_mass_in_excess_of_displaced_buffer: f64 = 110.0;
/// fg
pub const e_coli_mass_in_excess_of_displaced_buffer_min: f64 = 80.0;
/// fg
pub const e_coli_mass_in_excess_of_displaced_buffer_max: f64 = 140.0;
/// µM
pub const e_coli_total_amount_of_laci_repressor: f64 = 0.01;
/// µM
pub const e_coli_maximal_amount_of_lacz: f64 = 50.0;
/// µM
pub const e_coli_maximal_amount_of_lacy: f64 = 50.0;
/// Molecules / minute
pub const e_coli_velocity_of_allolactose_hydrolysis_by_lacz: f64 = 20_000.0;
/// μM
pub const e_coli_affinity_of_allolactose_and_laci: f64 = 6.0;
/// mM
pub const e_coli_affinity_of_allolactose_and_lacz: f64 = 1.9;
/// µmol / g
pub const e_coli_glutamine_pool_size: f64 = 3.92;
/// µmol / g
pub const e_coli_glutamine_pool_size_min: f64 = 3.75;
/// µmol / g
pub const e_coli_glutamine_pool_size_max: f64 = 4.09;
/// µmol / g
pub const e_coli_glutamate_pool_size: f64 = 100.55;
/// µmol / g
pub const e_coli_glutamate_pool_size_min: f64 = 83.001;
/// µmol / g
pub const e_coli_glutamate_pool_size_max: f64 = 118.09;
/// µmol / g
pub const e_coli_alanine_pool_size: f64 = 6.81;
/// µmol / g
pub const e_coli_alanine_pool_size_min: f64 = 5.102;
/// µmol / g
pub const e_coli_alanine_pool_size_max: f64 = 8.51;
/// µmol / g
pub const e_coli_asparagine_pool_size: f64 = 2.02;
/// µmol / g
pub const e_coli_asparagine_pool_size_min: f64 = 1.56;
/// µmol / g
pub const e_coli_asparagine_pool_size_max: f64 = 2.48;
/// µmol / g
pub const e_coli_aspartate_pool_size: f64 = 6.45;
/// µmol / g
pub const e_coli_aspartate_pool_size_min: f64 = 9.9;
/// µmol / g
pub const e_coli_aspartate_pool_size_max: f64 = 2.91;
/// µmol / g
pub const e_coli_methionine_pool_size: f64 = 0.29;
/// µmol / g
pub const e_coli_methionine_pool_size_min: f64 = 0.22;
/// µmol / g
pub const e_coli_methionine_pool_size_max: f64 = 0.36;
/// µmol / g
pub const e_coli_proline_pool_size: f64 = 1.1;
/// µmol / g
pub const e_coli_proline_pool_size_min: f64 = 0.95;
/// µmol / g
pub const e_coli_proline_pool_size_max: f64 = 1.25;
/// µmol / g
pub const e_coli_threonine_pool_size: f64 = 1.34;
/// µmol / g
pub const e_coli_threonine_pool_size_min: f64 = 1.50;
/// µmol / g
pub const e_coli_threonine_pool_size_max: f64 = 1.18;
/// µmol / g
pub const e_coli_tyrosine_pool_size: f64 = 0.41;
/// µmol / g
pub const e_coli_tyrosine_pool_size_min: f64 = 0.16;
/// µmol / g
pub const e_coli_tyrosine_pool_size_max: f64 = 0.66;
/// µmol / g
pub const e_coli_valine_pool_size: f64 = 2.41;
/// µmol / g
pub const e_coli_valine_pool_size_min: f64 = 2.14;
/// µmol / g
pub const e_coli_valine_pool_size_max: f64 = 2.68;
/// µmol / g
pub const e_coli_carbamoyl_aspartate_pool_size: f64 = 0.84;
/// µmol / g
pub const e_coli_carbamoyl_aspartate_pool_size_min: f64 = 0.56;
/// µmol / g
pub const e_coli_carbamoyl_aspartate_pool_size_max: f64 = 1.12;
/// µmol / g
pub const e_coli_imp_pool_size: f64 = 0.38;
/// µmol / g
pub const e_coli_imp_pool_size_min: f64 = 0.37;
/// µmol / g
pub const e_coli_imp_pool_size_max: f64 = 0.39;
/// %
pub const e_coli_percent_of_cell_total_dry_weight_that_is_lipopolysaccharide: f64 = 3.4;
/// Molecules / cell
pub const e_coli_reca_molecules_per_cell: f64 = 1000.0;
/// %
pub const e_coli_reca_molecules_per_cell_min: f64 = 800.0;
/// %
pub const e_coli_reca_molecules_per_cell_max: f64 = 1200.0;
/// µm^2/sec
pub const e_coli_apparent_diffusion_constant_of_protein_along_dna_segments: f64 = 0.4;
/// µm^2/sec
pub const e_coli_apparent_diffusion_constant_of_protein_along_dna_segments_min: f64 = 0.38;
/// µm^2/sec
pub const e_coli_apparent_diffusion_constant_of_protein_along_dna_segments_max: f64 = 0.42;
<|endoftext|>


<commit_before>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CString;
use std::mem;
use std::os::unix::io;
use std::ptr;

use callbacks::{
    socket_callback,
    query_a_callback,
    query_aaaa_callback,
};
use types::{
    Flag,
    AresError,
    AResult,
    AAAAResult,
    DnsClass,
    QueryType,
};
use utils::ares_error;

/// Used to configure the behaviour of the name resolver.
pub struct Options {
    ares_options: c_ares_sys::Struct_ares_options,
    optmask: libc::c_int,
    domains: Vec<CString>,
    lookups: Option<CString>,
}

impl Options {
    /// Returns a fresh `Options`, on which no values are set.
    pub fn new() -> Options {
        Options {
            ares_options: c_ares_sys::Struct_ares_options::default(),
            optmask: 0,
            domains: Vec::new(),
            lookups: None,
        }
    }

    /// Set flags controlling the behaviour of the resolver.
    pub fn set_flags(&mut self, flags: &[Flag]) -> &mut Self {
        let c_flags: libc::c_int = flags
            .iter()
            .fold(0, |acc, &flag| acc | (flag as libc::c_int));
        self.ares_options.flags = c_flags;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_FLAGS;
        self
    }

    /// Set the number of milliseconds each name server is given to respond to
    /// a query on the first try.  (After the first try, the timeout algorithm
    /// becomes more complicated, but scales linearly with the value of
    /// timeout.) The default is five seconds.
    pub fn set_timeout(&mut self, ms: u32) -> &mut Self {
        self.ares_options.timeout = ms as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_TIMEOUTMS;
        self
    }

    /// Set the number of tries the resolver will try contacting each name
    /// server before giving up. The default is four tries.
    pub fn set_tries(&mut self, tries: u32) -> &mut Self {
        self.ares_options.tries = tries as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_TRIES;
        self
    }

    /// Set the number of dots which must be present in a domain name for it to
    /// be queried for "as is" prior to querying for it with the default domain
    /// extensions appended. The default value is 1 unless set otherwise by
    /// resolv.conf or the RES_OPTIONS environment variable.
    pub fn set_ndots(&mut self, ndots: u32) -> &mut Self {
        self.ares_options.ndots = ndots as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_NDOTS;
        self
    }

    /// Set the UDP port to use for queries. The default value is 53, the
    /// standard name service port.
    pub fn set_udp_port(&mut self, udp_port: u16) -> &mut Self {
        self.ares_options.udp_port = udp_port as libc::c_ushort;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_UDP_PORT;
        self
    }

    /// Set the TCP port to use for queries. The default value is 53, the
    /// standard name service port.
    pub fn set_tcp_port(&mut self, tcp_port: u16) -> &mut Self {
        self.ares_options.tcp_port = tcp_port as libc::c_ushort;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_TCP_PORT;
        self
    }

    /// Set the domains to search, instead of the domains specified in
    /// resolv.conf or the domain derived from the kernel hostname variable.
    pub fn set_domains(&mut self, domains: &[&str]) -> &mut Self {
        self.domains = domains
            .iter()
            .map(|&s| CString::new(s).unwrap())
            .collect();
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_DOMAINS;
        self
    }

    /// Set the lookups to perform for host queries. `lookups` should be set to
    /// a string of the characters "b" or "f", where "b" indicates a DNS lookup
    /// and "f" indicates a lookup in the hosts file.
    pub fn set_lookups(&mut self, lookups: &str) -> &mut Self {
        let c_lookups = CString::new(lookups).unwrap();
        self.lookups = Some(c_lookups);
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_LOOKUPS;
        self
    }

    /// Set the socket send buffer size.
    pub fn set_sock_send_buffer_size(&mut self, size: u32) -> &mut Self {
        self.ares_options.socket_send_buffer_size = size as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_SOCK_SNDBUF;
        self
    }

    /// Set the socket receive buffer size.
    pub fn set_sock_receive_buffer_size(&mut self, size: u32) -> &mut Self {
        self.ares_options.socket_receive_buffer_size = size as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_SOCK_RCVBUF;
        self
    }

    /// Configure round robin selection of nameservers.
    pub fn set_rotate(&mut self) -> &mut Self {
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_ROTATE;
        self
    }

    /// Set the EDNS packet size.
    pub fn set_ednspsz(&mut self, size: u32) -> &mut Self {
        self.ares_options.ednspsz = size as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_EDNSPSZ;
        self
    }
}

/// A channel for name service lookups.
pub struct Channel {
    ares_channel: c_ares_sys::ares_channel,
}

impl Channel {
    /// Create a new channel for name service lookups, providing a callback
    /// for socket state changes.
    ///
    /// `callback(socket, read, write)` will be called when a socket changes
    /// state:
    ///
    /// -  `read` is set to true if the socket should listen for read events
    /// -  `write` is set to true if the socket should listen to write events.
    pub fn new<F>(
        callback: F,
        mut options: Options) -> Result<Channel, AresError>
        where F: FnMut(io::RawFd, bool, bool) + 'static {
        options.optmask = options.optmask | c_ares_sys::ARES_OPT_SOCK_STATE_CB;
        options.ares_options.sock_state_cb = Some(socket_callback::<F>);
        options.ares_options.sock_state_cb_data = unsafe {
            mem::transmute(Box::new(callback))
        };
        Self::create_channel(options)
    }

    fn create_channel(mut options: Options) -> Result<Channel, AresError> {
        // Initialize the library.
        let lib_rc = unsafe {
            c_ares_sys::ares_library_init(c_ares_sys::ARES_LIB_INIT_ALL)
        };
        if lib_rc != c_ares_sys::ARES_SUCCESS {
            return Err(ares_error(lib_rc))
        }

        // We deferred setting up domains in the options - do it now.
        let domains: Vec<_> = options.domains
            .iter()
            .map(|s| s.as_ptr())
            .collect();
        options.ares_options.domains =
            domains.as_ptr() as *mut *mut libc::c_char;
        options.ares_options.ndomains = domains.len() as libc::c_int;

        // Likewise for lookups.
        for c_lookup in options.lookups.iter() {
            options.ares_options.lookups =
                c_lookup.as_ptr() as *mut libc::c_char;
        }

        // Initialize the channel.
        let mut ares_channel = ptr::null_mut();
        let channel_rc = unsafe {
            c_ares_sys::ares_init_options(
                &mut ares_channel,
                &mut options.ares_options,
                options.optmask)
        };
        if channel_rc != c_ares_sys::ARES_SUCCESS {
            unsafe { c_ares_sys::ares_library_cleanup(); }
            return Err(ares_error(channel_rc))
        }

        let channel = Channel {
            ares_channel: ares_channel,
        };
        Ok(channel)
    }

    /// Handle input, output, and timeout events associated with the specified
    /// file descriptors (sockets).
    ///
    /// Providing a value for `read_fd` indicates that the identified socket
    /// is readable; likewise providing a value for `write_fd` indicates that
    /// the identified socket is writable.  Use `INVALID_FD` for "no action".
    pub fn process_fd(&mut self, read_fd: io::RawFd, write_fd: io::RawFd) {
        unsafe {
            c_ares_sys::ares_process_fd(
                self.ares_channel,
                read_fd as c_ares_sys::ares_socket_t,
                write_fd as c_ares_sys::ares_socket_t);
        }
    }

    /// Set the list of servers to contact, instead of the servers specified
    /// in resolv.conf or the local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require
    /// square brackets eg `[2001:4860:4860::8888]:53`.
    pub fn set_servers(&mut self, servers: &[&str]) -> Result<(), AresError> {
        let servers_csv = servers.connect(",");
        let c_servers = CString::new(servers_csv).unwrap();
        let ares_rc = unsafe {
            c_ares_sys::ares_set_servers_csv(
                self.ares_channel,
                c_servers.as_ptr())
        };
        if ares_rc != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(ares_rc))
        } else {
            Ok(())
        }
    }

    /// Look up the A record associated with `name`.
    ///
    /// On completion, `handler` is called with the result.
    pub fn query_a<F>(&mut self, name: &str, handler: F)
        where F: FnOnce(Result<AResult, AresError>) + 'static {
        let c_name = CString::new(name).unwrap();
        unsafe {
            let c_arg: *mut libc::c_void = mem::transmute(Box::new(handler));
            c_ares_sys::ares_query(
                self.ares_channel,
                c_name.as_ptr(),
                DnsClass::IN as libc::c_int,
                QueryType::A as libc::c_int,
                Some(query_a_callback::<F>),
                c_arg);
        }
    }

    /// Look up the AAAA record associated with `name`.
    ///
    /// On completion, `handler` is called with the result.
    pub fn query_aaaa<F>(&mut self, name: &str, handler: F)
        where F: FnOnce(Result<AAAAResult, AresError>) + 'static {
        let c_name = CString::new(name).unwrap();
        unsafe {
            let c_arg: *mut libc::c_void = mem::transmute(Box::new(handler));
            c_ares_sys::ares_query(
                self.ares_channel,
                c_name.as_ptr(),
                DnsClass::IN as libc::c_int,
                QueryType::AAAA as libc::c_int,
                Some(query_aaaa_callback::<F>),
                c_arg);
        }
    }
}

impl Drop for Channel {
    fn drop(&mut self) {
        unsafe {
            c_ares_sys::ares_destroy(self.ares_channel);
            c_ares_sys::ares_library_cleanup();
        }
    }
}

unsafe impl Send for Channel { }
<commit_msg>Derive Clone and Debug where we can<commit_after>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CString;
use std::mem;
use std::os::unix::io;
use std::ptr;

use callbacks::{
    socket_callback,
    query_a_callback,
    query_aaaa_callback,
};
use types::{
    Flag,
    AresError,
    AResult,
    AAAAResult,
    DnsClass,
    QueryType,
};
use utils::ares_error;

/// Used to configure the behaviour of the name resolver.
#[derive(Clone)]
pub struct Options {
    ares_options: c_ares_sys::Struct_ares_options,
    optmask: libc::c_int,
    domains: Vec<CString>,
    lookups: Option<CString>,
}

impl Options {
    /// Returns a fresh `Options`, on which no values are set.
    pub fn new() -> Options {
        Options {
            ares_options: c_ares_sys::Struct_ares_options::default(),
            optmask: 0,
            domains: Vec::new(),
            lookups: None,
        }
    }

    /// Set flags controlling the behaviour of the resolver.
    pub fn set_flags(&mut self, flags: &[Flag]) -> &mut Self {
        let c_flags: libc::c_int = flags
            .iter()
            .fold(0, |acc, &flag| acc | (flag as libc::c_int));
        self.ares_options.flags = c_flags;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_FLAGS;
        self
    }

    /// Set the number of milliseconds each name server is given to respond to
    /// a query on the first try.  (After the first try, the timeout algorithm
    /// becomes more complicated, but scales linearly with the value of
    /// timeout.) The default is five seconds.
    pub fn set_timeout(&mut self, ms: u32) -> &mut Self {
        self.ares_options.timeout = ms as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_TIMEOUTMS;
        self
    }

    /// Set the number of tries the resolver will try contacting each name
    /// server before giving up. The default is four tries.
    pub fn set_tries(&mut self, tries: u32) -> &mut Self {
        self.ares_options.tries = tries as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_TRIES;
        self
    }

    /// Set the number of dots which must be present in a domain name for it to
    /// be queried for "as is" prior to querying for it with the default domain
    /// extensions appended. The default value is 1 unless set otherwise by
    /// resolv.conf or the RES_OPTIONS environment variable.
    pub fn set_ndots(&mut self, ndots: u32) -> &mut Self {
        self.ares_options.ndots = ndots as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_NDOTS;
        self
    }

    /// Set the UDP port to use for queries. The default value is 53, the
    /// standard name service port.
    pub fn set_udp_port(&mut self, udp_port: u16) -> &mut Self {
        self.ares_options.udp_port = udp_port as libc::c_ushort;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_UDP_PORT;
        self
    }

    /// Set the TCP port to use for queries. The default value is 53, the
    /// standard name service port.
    pub fn set_tcp_port(&mut self, tcp_port: u16) -> &mut Self {
        self.ares_options.tcp_port = tcp_port as libc::c_ushort;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_TCP_PORT;
        self
    }

    /// Set the domains to search, instead of the domains specified in
    /// resolv.conf or the domain derived from the kernel hostname variable.
    pub fn set_domains(&mut self, domains: &[&str]) -> &mut Self {
        self.domains = domains
            .iter()
            .map(|&s| CString::new(s).unwrap())
            .collect();
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_DOMAINS;
        self
    }

    /// Set the lookups to perform for host queries. `lookups` should be set to
    /// a string of the characters "b" or "f", where "b" indicates a DNS lookup
    /// and "f" indicates a lookup in the hosts file.
    pub fn set_lookups(&mut self, lookups: &str) -> &mut Self {
        let c_lookups = CString::new(lookups).unwrap();
        self.lookups = Some(c_lookups);
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_LOOKUPS;
        self
    }

    /// Set the socket send buffer size.
    pub fn set_sock_send_buffer_size(&mut self, size: u32) -> &mut Self {
        self.ares_options.socket_send_buffer_size = size as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_SOCK_SNDBUF;
        self
    }

    /// Set the socket receive buffer size.
    pub fn set_sock_receive_buffer_size(&mut self, size: u32) -> &mut Self {
        self.ares_options.socket_receive_buffer_size = size as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_SOCK_RCVBUF;
        self
    }

    /// Configure round robin selection of nameservers.
    pub fn set_rotate(&mut self) -> &mut Self {
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_ROTATE;
        self
    }

    /// Set the EDNS packet size.
    pub fn set_ednspsz(&mut self, size: u32) -> &mut Self {
        self.ares_options.ednspsz = size as libc::c_int;
        self.optmask = self.optmask | c_ares_sys::ARES_OPT_EDNSPSZ;
        self
    }
}

/// A channel for name service lookups.
#[derive(Clone, Debug)]
pub struct Channel {
    ares_channel: c_ares_sys::ares_channel,
}

impl Channel {
    /// Create a new channel for name service lookups, providing a callback
    /// for socket state changes.
    ///
    /// `callback(socket, read, write)` will be called when a socket changes
    /// state:
    ///
    /// -  `read` is set to true if the socket should listen for read events
    /// -  `write` is set to true if the socket should listen to write events.
    pub fn new<F>(
        callback: F,
        mut options: Options) -> Result<Channel, AresError>
        where F: FnMut(io::RawFd, bool, bool) + 'static {
        options.optmask = options.optmask | c_ares_sys::ARES_OPT_SOCK_STATE_CB;
        options.ares_options.sock_state_cb = Some(socket_callback::<F>);
        options.ares_options.sock_state_cb_data = unsafe {
            mem::transmute(Box::new(callback))
        };
        Self::create_channel(options)
    }

    fn create_channel(mut options: Options) -> Result<Channel, AresError> {
        // Initialize the library.
        let lib_rc = unsafe {
            c_ares_sys::ares_library_init(c_ares_sys::ARES_LIB_INIT_ALL)
        };
        if lib_rc != c_ares_sys::ARES_SUCCESS {
            return Err(ares_error(lib_rc))
        }

        // We deferred setting up domains in the options - do it now.
        let domains: Vec<_> = options.domains
            .iter()
            .map(|s| s.as_ptr())
            .collect();
        options.ares_options.domains =
            domains.as_ptr() as *mut *mut libc::c_char;
        options.ares_options.ndomains = domains.len() as libc::c_int;

        // Likewise for lookups.
        for c_lookup in options.lookups.iter() {
            options.ares_options.lookups =
                c_lookup.as_ptr() as *mut libc::c_char;
        }

        // Initialize the channel.
        let mut ares_channel = ptr::null_mut();
        let channel_rc = unsafe {
            c_ares_sys::ares_init_options(
                &mut ares_channel,
                &mut options.ares_options,
                options.optmask)
        };
        if channel_rc != c_ares_sys::ARES_SUCCESS {
            unsafe { c_ares_sys::ares_library_cleanup(); }
            return Err(ares_error(channel_rc))
        }

        let channel = Channel {
            ares_channel: ares_channel,
        };
        Ok(channel)
    }

    /// Handle input, output, and timeout events associated with the specified
    /// file descriptors (sockets).
    ///
    /// Providing a value for `read_fd` indicates that the identified socket
    /// is readable; likewise providing a value for `write_fd` indicates that
    /// the identified socket is writable.  Use `INVALID_FD` for "no action".
    pub fn process_fd(&mut self, read_fd: io::RawFd, write_fd: io::RawFd) {
        unsafe {
            c_ares_sys::ares_process_fd(
                self.ares_channel,
                read_fd as c_ares_sys::ares_socket_t,
                write_fd as c_ares_sys::ares_socket_t);
        }
    }

    /// Set the list of servers to contact, instead of the servers specified
    /// in resolv.conf or the local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require
    /// square brackets eg `[2001:4860:4860::8888]:53`.
    pub fn set_servers(&mut self, servers: &[&str]) -> Result<(), AresError> {
        let servers_csv = servers.connect(",");
        let c_servers = CString::new(servers_csv).unwrap();
        let ares_rc = unsafe {
            c_ares_sys::ares_set_servers_csv(
                self.ares_channel,
                c_servers.as_ptr())
        };
        if ares_rc != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(ares_rc))
        } else {
            Ok(())
        }
    }

    /// Look up the A record associated with `name`.
    ///
    /// On completion, `handler` is called with the result.
    pub fn query_a<F>(&mut self, name: &str, handler: F)
        where F: FnOnce(Result<AResult, AresError>) + 'static {
        let c_name = CString::new(name).unwrap();
        unsafe {
            let c_arg: *mut libc::c_void = mem::transmute(Box::new(handler));
            c_ares_sys::ares_query(
                self.ares_channel,
                c_name.as_ptr(),
                DnsClass::IN as libc::c_int,
                QueryType::A as libc::c_int,
                Some(query_a_callback::<F>),
                c_arg);
        }
    }

    /// Look up the AAAA record associated with `name`.
    ///
    /// On completion, `handler` is called with the result.
    pub fn query_aaaa<F>(&mut self, name: &str, handler: F)
        where F: FnOnce(Result<AAAAResult, AresError>) + 'static {
        let c_name = CString::new(name).unwrap();
        unsafe {
            let c_arg: *mut libc::c_void = mem::transmute(Box::new(handler));
            c_ares_sys::ares_query(
                self.ares_channel,
                c_name.as_ptr(),
                DnsClass::IN as libc::c_int,
                QueryType::AAAA as libc::c_int,
                Some(query_aaaa_callback::<F>),
                c_arg);
        }
    }
}

impl Drop for Channel {
    fn drop(&mut self) {
        unsafe {
            c_ares_sys::ares_destroy(self.ares_channel);
            c_ares_sys::ares_library_cleanup();
        }
    }
}

unsafe impl Send for Channel { }
<|endoftext|>


<commit_before>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate image;
extern crate bytemuck;

use std::io::Cursor;
use image::ImageResult;
use image::codecs::openexr::*;
use image::Rgba32FImage;
use image::error::LimitError;
use image::ImageError;
use image::ImageBuffer;
use image::Rgb32FImage;
use std::io::Seek;
use std::io::BufRead;

// "just dont panic"
fn roundtrip(bytes: &[u8]) -> ImageResult<()> {
    use std::io::Write;

    /// Read the file from the specified path into an `Rgba32FImage`.
    // TODO this method should probably already exist in the main image crate
    fn read_as_rgba_byte_image(read: impl BufRead + Seek) -> ImageResult<(usize,usize,Vec<u8>)> {
        let decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?;
        let (width, height) = decoder.dimensions();

        let mut buffer = vec![0; usize::try_from(decoder.total_bytes()).unwrap()];
        decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?;

        Ok((width, height, buffer))
    }

    /// Write an `Rgba32FImage`.
    /// Assumes the writer is buffered. In most cases,
    /// you should wrap your writer in a `BufWriter` for best performance.
    // TODO this method should probably already exist in the main image crate
    fn write_rgba_image(write: impl Write/* + Seek*/, image: &Rgba32FImage) -> ImageResult<()> {
        OpenExrEncoder::new(write).write_image(
            bytemuck::cast_slice(image.as_raw().as_slice()),
            image.width(), image.height(),
            ColorType::Rgba32F
        )
    }

    let decoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?;

    let mut bytes = Vec::with_capacity(bytes.len() + 20);
    write_rgba_image(Cursor::new(&mut bytes), &decoded_image)?;

    let redecoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?;

    // if both images are valid, assert read/write consistency
    assert_eq!(decoded_image, redecoded_image, "image was valid but was not reproducible");
    Ok(())
}

fuzz_target!(|data: &[u8]| {
    let _img = roundtrip(data); // fixme not optimized away?
});
<commit_msg>fix unused crate import error<commit_after>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate image;

use std::io::Cursor;
use image::ImageResult;
use image::codecs::openexr::*;
use image::Rgba32FImage;
use image::error::LimitError;
use image::ImageError;
use image::ImageBuffer;
use image::Rgb32FImage;
use std::io::Seek;
use std::io::BufRead;

// "just dont panic"
fn roundtrip(bytes: &[u8]) -> ImageResult<()> {
    use std::io::Write;

    /// Read the file from the specified path into an `Rgba32FImage`.
    // TODO this method should probably already exist in the main image crate
    fn read_as_rgba_byte_image(read: impl BufRead + Seek) -> ImageResult<(usize,usize,Vec<u8>)> {
        let decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?;
        let (width, height) = decoder.dimensions();

        let mut buffer = vec![0; usize::try_from(decoder.total_bytes()).unwrap()];
        decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?;

        Ok((width, height, buffer))
    }

    /// Write an `Rgba32FImage`.
    /// Assumes the writer is buffered. In most cases,
    /// you should wrap your writer in a `BufWriter` for best performance.
    // TODO this method should probably already exist in the main image crate
    fn write_rgba_image(write: impl Write/* + Seek*/, image: &Rgba32FImage) -> ImageResult<()> {
        OpenExrEncoder::new(write).write_image(
            bytemuck::cast_slice(image.as_raw().as_slice()),
            image.width(), image.height(),
            ColorType::Rgba32F
        )
    }

    let decoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?;

    let mut bytes = Vec::with_capacity(bytes.len() + 20);
    write_rgba_image(Cursor::new(&mut bytes), &decoded_image)?;

    let redecoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?;

    // if both images are valid, assert read/write consistency
    assert_eq!(decoded_image, redecoded_image, "image was valid but was not reproducible");
    Ok(())
}

fuzz_target!(|data: &[u8]| {
    let _img = roundtrip(data); // fixme not optimized away?
});
<|endoftext|>


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

use super::*;

#[derive(Debug, Clone)]
#[doc(hidden)]
pub struct Context {
    // TODO file from config should be in here
    config: RunningConfig,
    /// Periodically flushes dirty data. We keep this in an
    /// Arc separate from the PageCache below to separate
    /// "high-level" references from Db, Tree etc... from
    /// "low-level" references like background threads.
    /// When the last high-level reference is dropped, it
    /// should trigger all background threads to clean
    /// up synchronously.
    #[cfg(any(
        windows,
        target_os = "linux",
        target_os = "macos",
        target_os = "dragonfly",
        target_os = "freebsd",
        target_os = "openbsd",
        target_os = "netbsd",
    ))]
    pub(crate) flusher: Arc<Mutex<Option<flusher::Flusher>>>,
    #[doc(hidden)]
    pub pagecache: Arc<PageCache>,
}

impl std::ops::Deref for Context {
    type Target = RunningConfig;

    fn deref(&self) -> &RunningConfig {
        &self.config
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        loop {
            match self.pagecache.flush() {
                Ok(0) => return,
                Ok(_) => continue,
                Err(e) => {
                    error!(
                        "failed to flush underlying \
                         pagecache during drop: {:?}",
                        e
                    );
                    return;
                }
            }
        }
    }
}

impl Context {
    pub(crate) fn start(config: RunningConfig) -> Result<Self> {
        trace!("starting context");

        let pagecache = Arc::new(PageCache::start(config.clone())?);

        Ok(Self {
            config,
            pagecache,
            #[cfg(any(windows, target_os = "linux", target_os = "macos"))]
            flusher: Arc::new(parking_lot::Mutex::new(None)),
        })
    }

    /// Returns `true` if the database was
    /// recovered from a previous process.
    /// Note that database state is only
    /// guaranteed to be present up to the
    /// last call to `flush`! Otherwise state
    /// is synced to disk periodically if the
    /// `sync_every_ms` configuration option
    /// is set to `Some(number_of_ms_between_syncs)`
    /// or if the IO buffer gets filled to
    /// capacity before being rotated.
    pub fn was_recovered(&self) -> bool {
        self.pagecache.was_recovered()
    }

    /// Generate a monotonic ID. Not guaranteed to be
    /// contiguous. Written to disk every `idgen_persist_interval`
    /// operations, followed by a blocking flush. During recovery, we
    /// take the last recovered generated ID and add 2x
    /// the `idgen_persist_interval` to it. While persisting, if the
    /// previous persisted counter wasn't synced to disk yet, we will do
    /// a blocking flush to fsync the latest counter, ensuring
    /// that we will never give out the same counter twice.
    pub fn generate_id(&self) -> Result<u64> {
        self.pagecache.generate_id()
    }

    pub(crate) fn pin_log(&self, guard: &Guard) -> Result<RecoveryGuard<'_>> {
        self.pagecache.pin_log(guard)
    }
}
<commit_msg>Fix conditional compilation<commit_after>use std::sync::Arc;

use super::*;

#[derive(Debug, Clone)]
#[doc(hidden)]
pub struct Context {
    // TODO file from config should be in here
    config: RunningConfig,
    /// Periodically flushes dirty data. We keep this in an
    /// Arc separate from the PageCache below to separate
    /// "high-level" references from Db, Tree etc... from
    /// "low-level" references like background threads.
    /// When the last high-level reference is dropped, it
    /// should trigger all background threads to clean
    /// up synchronously.
    #[cfg(any(
        windows,
        target_os = "linux",
        target_os = "macos",
        target_os = "dragonfly",
        target_os = "freebsd",
        target_os = "openbsd",
        target_os = "netbsd",
    ))]
    pub(crate) flusher: Arc<Mutex<Option<flusher::Flusher>>>,
    #[doc(hidden)]
    pub pagecache: Arc<PageCache>,
}

impl std::ops::Deref for Context {
    type Target = RunningConfig;

    fn deref(&self) -> &RunningConfig {
        &self.config
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        loop {
            match self.pagecache.flush() {
                Ok(0) => return,
                Ok(_) => continue,
                Err(e) => {
                    error!(
                        "failed to flush underlying \
                         pagecache during drop: {:?}",
                        e
                    );
                    return;
                }
            }
        }
    }
}

impl Context {
    pub(crate) fn start(config: RunningConfig) -> Result<Self> {
        trace!("starting context");

        let pagecache = Arc::new(PageCache::start(config.clone())?);

        Ok(Self {
            config,
            pagecache,
            #[cfg(any(
                windows,
                target_os = "linux",
                target_os = "macos",
                target_os = "dragonfly",
                target_os = "freebsd",
                target_os = "openbsd",
                target_os = "netbsd",
            ))]
            flusher: Arc::new(parking_lot::Mutex::new(None)),
        })
    }

    /// Returns `true` if the database was
    /// recovered from a previous process.
    /// Note that database state is only
    /// guaranteed to be present up to the
    /// last call to `flush`! Otherwise state
    /// is synced to disk periodically if the
    /// `sync_every_ms` configuration option
    /// is set to `Some(number_of_ms_between_syncs)`
    /// or if the IO buffer gets filled to
    /// capacity before being rotated.
    pub fn was_recovered(&self) -> bool {
        self.pagecache.was_recovered()
    }

    /// Generate a monotonic ID. Not guaranteed to be
    /// contiguous. Written to disk every `idgen_persist_interval`
    /// operations, followed by a blocking flush. During recovery, we
    /// take the last recovered generated ID and add 2x
    /// the `idgen_persist_interval` to it. While persisting, if the
    /// previous persisted counter wasn't synced to disk yet, we will do
    /// a blocking flush to fsync the latest counter, ensuring
    /// that we will never give out the same counter twice.
    pub fn generate_id(&self) -> Result<u64> {
        self.pagecache.generate_id()
    }

    pub(crate) fn pin_log(&self, guard: &Guard) -> Result<RecoveryGuard<'_>> {
        self.pagecache.pin_log(guard)
    }
}
<|endoftext|>