text:
pub struct Fiery {
    pub message: ::std::string::String,
    // This field forces `..Default::default()` when instantiating this
    // struct, to make code future-proof against new fields added later to
    // the definition in Thrift. If you don't want this, add the annotation
    // `(rust.exhaustive)` to the Thrift struct to eliminate this field.
    #[doc(hidden)]
    pub _dot_dot_Default_default: self::dot_dot::OtherFields,
}

impl ::fbthrift::ExceptionInfo for Fiery {
    fn exn_value(&self) -> String {
        format!("{:?}", self)
    }

    #[inline]
    fn exn_is_declared(&self) -> bool { true }
}

impl ::std::error::Error for Fiery {}

impl ::std::fmt::Display for Fiery {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Fiery: {}: {:?}", self.message, self)
    }
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Serious {
    pub sonnet: ::std::option::Option<::std::string::String>,
    // This field forces `..Default::default()` when instantiating this
    // struct, to make code future-proof against new fields added later to
    // the definition in Thrift. If you don't want this, add the annotation
    // `(rust.exhaustive)` to the Thrift struct to eliminate this field.
    #[doc(hidden)]
    pub _dot_dot_Default_default: self::dot_dot::OtherFields,
}

impl ::fbthrift::ExceptionInfo for Serious {
    fn exn_value(&self) -> String {
        format!("{:?}", self)
    }

    #[inline]
    fn exn_is_declared(&self) -> bool { true }
}

impl ::std::error::Error for Serious {}

impl ::std::fmt::Display for Serious {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Serious: {:?}: {:?}", self.sonnet, self)
    }
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ComplexFieldNames {
    pub error_message: ::std::string::String,
    pub internal_error_message: ::std::string::String,
    // This field forces `..Default::default()` when instantiating this
    // struct, to make code future-proof against new fields added later to
    // the definition in Thrift. If you don't want this, add the annotation
    // `(rust.exhaustive)` to the Thrift struct to eliminate this field.
    #[doc(hidden)]
    pub _dot_dot_Default_default: self::dot_dot::OtherFields,
}

impl ::fbthrift::ExceptionInfo for ComplexFieldNames {
    fn exn_value(&self) -> String {
        format!("{:?}", self)
    }

    #[inline]
    fn exn_is_declared(&self) -> bool { true }
}

impl ::std::error::Error for ComplexFieldNames {}

impl ::std::fmt::Display for ComplexFieldNames {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "ComplexFieldNames: {}: {:?}", self.internal_error_message, self)
    }
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CustomFieldNames {
    pub error_message: ::std::string::String,
    pub internal_error_message: ::std::string::String,
    // This field forces `..Default::default()` when instantiating this
    // struct, to make code future-proof against new fields added later to
    // the definition in Thrift. If you don't want this, add the annotation
    // `(rust.exhaustive)` to the Thrift struct to eliminate this field.
    #[doc(hidden)]
    pub _dot_dot_Default_default: self::dot_dot::OtherFields,
}

impl ::fbthrift::ExceptionInfo for CustomFieldNames {
    fn exn_value(&self) -> String {
        format!("{:?}", self)
    }

    #[inline]
    fn exn_is_declared(&self) -> bool { true }
}

impl ::std::error::Error for CustomFieldNames {}

impl ::std::fmt::Display for CustomFieldNames {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "CustomFieldNames: {}: {:?}", self.internal_error_message, self)
    }
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ExceptionWithPrimitiveField {
    pub message: ::std::string::String,
    pub error_code: ::std::primitive::i32,
    // This field forces `..Default::default()` when instantiating this
    // struct, to make code future-proof against new fields added later to
    // the definition in Thrift. If you don't want this, add the annotation
    // `(rust.exhaustive)` to the Thrift struct to eliminate this field.
    #[doc(hidden)]
    pub _dot_dot_Default_default: self::dot_dot::OtherFields,
}

impl ::fbthrift::ExceptionInfo for ExceptionWithPrimitiveField {
    fn exn_value(&self) -> String {
        format!("{:?}", self)
    }

    #[inline]
    fn exn_is_declared(&self) -> bool { true }
}

impl ::std::error::Error for ExceptionWithPrimitiveField {}

impl ::std::fmt::Display for ExceptionWithPrimitiveField {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "ExceptionWithPrimitiveField: {}: {:?}", self.message, self)
    }
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ExceptionWithStructuredAnnotation {
    pub message_field: ::std::string::String,
    pub error_code: ::std::primitive::i32,
    // This field forces `..Default::default()` when instantiating this
    // struct, to make code future-proof against new fields added later to
    // the definition in Thrift. If you don't want this, add the annotation
    // `(rust.exhaustive)` to the Thrift struct to eliminate this field.
    #[doc(hidden)]
    pub _dot_dot_Default_default: self::dot_dot::OtherFields,
}

impl ::fbthrift::ExceptionInfo for ExceptionWithStructuredAnnotation {
    fn exn_value(&self) -> String {
        format!("{:?}", self)
    }

    #[inline]
    fn exn_is_declared(&self) -> bool { true }
}

impl ::std::error::Error for ExceptionWithStructuredAnnotation {}

impl ::std::fmt::Display for ExceptionWithStructuredAnnotation {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Banal {
    // This field forces `..Default::default()` when instantiating this
    // struct, to make code future-proof against new fields added later to
    // the definition in Thrift. If you don't want this, add the annotation
    // `(rust.exhaustive)` to the Thrift struct to eliminate this field.
    #[doc(hidden)]
    pub _dot_dot_Default_default: self::dot_dot::OtherFields,
}

impl ::fbthrift::ExceptionInfo for Banal {
    fn exn_value(&self) -> String {
        format!("{:?}", self)
    }

    #[inline]
    fn exn_is_declared(&self) -> bool { true }
}

impl ::std::error::Error for Banal {}

impl ::std::fmt::Display for Banal {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

#[allow(clippy::derivable_impls)]
impl ::std::default::Default for self::Fiery {
    fn default() -> Self {
        Self {
            message: ::std::default::Default::default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        }
    }
}

impl ::std::fmt::Debug for self::Fiery {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        formatter
            .debug_struct("Fiery")
            .field("message", &self.message)
            .finish()
    }
}

unsafe impl ::std::marker::Send for self::Fiery {}
unsafe impl ::std::marker::Sync for self::Fiery {}

impl ::fbthrift::GetTType for self::Fiery {
    const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
}

impl<P> ::fbthrift::Serialize<P> for self::Fiery
where
    P: ::fbthrift::ProtocolWriter,
{
    fn write(&self, p: &mut P) {
        p.write_struct_begin("Fiery");
        p.write_field_begin("message", ::fbthrift::TType::String, 1);
        ::fbthrift::Serialize::write(&self.message, p);
        p.write_field_end();
        p.write_field_stop();
        p.write_struct_end();
    }
}

impl<P> ::fbthrift::Deserialize<P> for self::Fiery
where
    P: ::fbthrift::ProtocolReader,
{
    fn read(p: &mut P) -> ::anyhow::Result<Self> {
        static FIELDS: &[::fbthrift::Field] = &[
            ::fbthrift::Field::new("message", ::fbthrift::TType::String, 1),
        ];
        let mut field_message = ::std::option::Option::None;
        let _ = p.read_struct_begin(|_| ())?;
        loop {
            let (_, fty, fid) = p.read_field_begin(|_| (), FIELDS)?;
            match (fty, fid as ::std::primitive::i32) {
                (::fbthrift::TType::Stop, _) => break,
                (::fbthrift::TType::String, 1) => field_message = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (fty, _) => p.skip(fty)?,
            }
            p.read_field_end()?;
        }
        p.read_struct_end()?;
        ::std::result::Result::Ok(Self {
            message: field_message.unwrap_or_default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        })
    }
}

#[allow(clippy::derivable_impls)]
impl ::std::default::Default for self::Serious {
    fn default() -> Self {
        Self {
            sonnet: ::std::option::Option::None,
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        }
    }
}

impl ::std::fmt::Debug for self::Serious {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        formatter
            .debug_struct("Serious")
            .field("sonnet", &self.sonnet)
            .finish()
    }
}

unsafe impl ::std::marker::Send for self::Serious {}
unsafe impl ::std::marker::Sync for self::Serious {}

impl ::fbthrift::GetTType for self::Serious {
    const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
}

impl<P> ::fbthrift::Serialize<P> for self::Serious
where
    P: ::fbthrift::ProtocolWriter,
{
    fn write(&self, p: &mut P) {
        p.write_struct_begin("Serious");
        if let ::std::option::Option::Some(some) = &self.sonnet {
            p.write_field_begin("sonnet", ::fbthrift::TType::String, 1);
            ::fbthrift::Serialize::write(some, p);
            p.write_field_end();
        }
        p.write_field_stop();
        p.write_struct_end();
    }
}

impl<P> ::fbthrift::Deserialize<P> for self::Serious
where
    P: ::fbthrift::ProtocolReader,
{
    fn read(p: &mut P) -> ::anyhow::Result<Self> {
        static FIELDS: &[::fbthrift::Field] = &[
            ::fbthrift::Field::new("sonnet", ::fbthrift::TType::String, 1),
        ];
        let mut field_sonnet = ::std::option::Option::None;
        let _ = p.read_struct_begin(|_| ())?;
        loop {
            let (_, fty, fid) = p.read_field_begin(|_| (), FIELDS)?;
            match (fty, fid as ::std::primitive::i32) {
                (::fbthrift::TType::Stop, _) => break,
                (::fbthrift::TType::String, 1) => field_sonnet = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (fty, _) => p.skip(fty)?,
            }
            p.read_field_end()?;
        }
        p.read_struct_end()?;
        ::std::result::Result::Ok(Self {
            sonnet: field_sonnet,
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        })
    }
}

#[allow(clippy::derivable_impls)]
impl ::std::default::Default for self::ComplexFieldNames {
    fn default() -> Self {
        Self {
            error_message: ::std::default::Default::default(),
            internal_error_message: ::std::default::Default::default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        }
    }
}

impl ::std::fmt::Debug for self::ComplexFieldNames {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        formatter
            .debug_struct("ComplexFieldNames")
            .field("error_message", &self.error_message)
            .field("internal_error_message", &self.internal_error_message)
            .finish()
    }
}

unsafe impl ::std::marker::Send for self::ComplexFieldNames {}
unsafe impl ::std::marker::Sync for self::ComplexFieldNames {}

impl ::fbthrift::GetTType for self::ComplexFieldNames {
    const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
}

impl<P> ::fbthrift::Serialize<P> for self::ComplexFieldNames
where
    P: ::fbthrift::ProtocolWriter,
{
    fn write(&self, p: &mut P) {
        p.write_struct_begin("ComplexFieldNames");
        p.write_field_begin("error_message", ::fbthrift::TType::String, 1);
        ::fbthrift::Serialize::write(&self.error_message, p);
        p.write_field_end();
        p.write_field_begin("internal_error_message", ::fbthrift::TType::String, 2);
        ::fbthrift::Serialize::write(&self.internal_error_message, p);
        p.write_field_end();
        p.write_field_stop();
        p.write_struct_end();
    }
}

impl<P> ::fbthrift::Deserialize<P> for self::ComplexFieldNames
where
    P: ::fbthrift::ProtocolReader,
{
    fn read(p: &mut P) -> ::anyhow::Result<Self> {
        static FIELDS: &[::fbthrift::Field] = &[
            ::fbthrift::Field::new("error_message", ::fbthrift::TType::String, 1),
            ::fbthrift::Field::new("internal_error_message", ::fbthrift::TType::String, 2),
        ];
        let mut field_error_message = ::std::option::Option::None;
        let mut field_internal_error_message = ::std::option::Option::None;
        let _ = p.read_struct_begin(|_| ())?;
        loop {
            let (_, fty, fid) = p.read_field_begin(|_| (), FIELDS)?;
            match (fty, fid as ::std::primitive::i32) {
                (::fbthrift::TType::Stop, _) => break,
                (::fbthrift::TType::String, 1) => field_error_message = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (::fbthrift::TType::String, 2) => field_internal_error_message = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (fty, _) => p.skip(fty)?,
            }
            p.read_field_end()?;
        }
        p.read_struct_end()?;
        ::std::result::Result::Ok(Self {
            error_message: field_error_message.unwrap_or_default(),
            internal_error_message: field_internal_error_message.unwrap_or_default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        })
    }
}

#[allow(clippy::derivable_impls)]
impl ::std::default::Default for self::CustomFieldNames {
    fn default() -> Self {
        Self {
            error_message: ::std::default::Default::default(),
            internal_error_message: ::std::default::Default::default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        }
    }
}

impl ::std::fmt::Debug for self::CustomFieldNames {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        formatter
            .debug_struct("CustomFieldNames")
            .field("error_message", &self.error_message)
            .field("internal_error_message", &self.internal_error_message)
            .finish()
    }
}

unsafe impl ::std::marker::Send for self::CustomFieldNames {}
unsafe impl ::std::marker::Sync for self::CustomFieldNames {}

impl ::fbthrift::GetTType for self::CustomFieldNames {
    const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
}

impl<P> ::fbthrift::Serialize<P> for self::CustomFieldNames
where
    P: ::fbthrift::ProtocolWriter,
{
    fn write(&self, p: &mut P) {
        p.write_struct_begin("CustomFieldNames");
        p.write_field_begin("error_message", ::fbthrift::TType::String, 1);
        ::fbthrift::Serialize::write(&self.error_message, p);
        p.write_field_end();
        p.write_field_begin("internal_error_message", ::fbthrift::TType::String, 2);
        ::fbthrift::Serialize::write(&self.internal_error_message, p);
        p.write_field_end();
        p.write_field_stop();
        p.write_struct_end();
    }
}

impl<P> ::fbthrift::Deserialize<P> for self::CustomFieldNames
where
    P: ::fbthrift::ProtocolReader,
{
    fn read(p: &mut P) -> ::anyhow::Result<Self> {
        static FIELDS: &[::fbthrift::Field] = &[
            ::fbthrift::Field::new("error_message", ::fbthrift::TType::String, 1),
            ::fbthrift::Field::new("internal_error_message", ::fbthrift::TType::String, 2),
        ];
        let mut field_error_message = ::std::option::Option::None;
        let mut field_internal_error_message = ::std::option::Option::None;
        let _ = p.read_struct_begin(|_| ())?;
        loop {
            let (_, fty, fid) = p.read_field_begin(|_| (), FIELDS)?;
            match (fty, fid as ::std::primitive::i32) {
                (::fbthrift::TType::Stop, _) => break,
                (::fbthrift::TType::String, 1) => field_error_message = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (::fbthrift::TType::String, 2) => field_internal_error_message = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (fty, _) => p.skip(fty)?,
            }
            p.read_field_end()?;
        }
        p.read_struct_end()?;
        ::std::result::Result::Ok(Self {
            error_message: field_error_message.unwrap_or_default(),
            internal_error_message: field_internal_error_message.unwrap_or_default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        })
    }
}

#[allow(clippy::derivable_impls)]
impl ::std::default::Default for self::ExceptionWithPrimitiveField {
    fn default() -> Self {
        Self {
            message: ::std::default::Default::default(),
            error_code: ::std::default::Default::default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        }
    }
}

impl ::std::fmt::Debug for self::ExceptionWithPrimitiveField {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        formatter
            .debug_struct("ExceptionWithPrimitiveField")
            .field("message", &self.message)
            .field("error_code", &self.error_code)
            .finish()
    }
}

unsafe impl ::std::marker::Send for self::ExceptionWithPrimitiveField {}
unsafe impl ::std::marker::Sync for self::ExceptionWithPrimitiveField {}

impl ::fbthrift::GetTType for self::ExceptionWithPrimitiveField {
    const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
}

impl<P> ::fbthrift::Serialize<P> for self::ExceptionWithPrimitiveField
where
    P: ::fbthrift::ProtocolWriter,
{
    fn write(&self, p: &mut P) {
        p.write_struct_begin("ExceptionWithPrimitiveField");
        p.write_field_begin("message", ::fbthrift::TType::String, 1);
        ::fbthrift::Serialize::write(&self.message, p);
        p.write_field_end();
        p.write_field_begin("error_code", ::fbthrift::TType::I32, 2);
        ::fbthrift::Serialize::write(&self.error_code, p);
        p.write_field_end();
        p.write_field_stop();
        p.write_struct_end();
    }
}

impl<P> ::fbthrift::Deserialize<P> for self::ExceptionWithPrimitiveField
where
    P: ::fbthrift::ProtocolReader,
{
    fn read(p: &mut P) -> ::anyhow::Result<Self> {
        static FIELDS: &[::fbthrift::Field] = &[
            ::fbthrift::Field::new("error_code", ::fbthrift::TType::I32, 2),
            ::fbthrift::Field::new("message", ::fbthrift::TType::String, 1),
        ];
        let mut field_message = ::std::option::Option::None;
        let mut field_error_code = ::std::option::Option::None;
        let _ = p.read_struct_begin(|_| ())?;
        loop {
            let (_, fty, fid) = p.read_field_begin(|_| (), FIELDS)?;
            match (fty, fid as ::std::primitive::i32) {
                (::fbthrift::TType::Stop, _) => break,
                (::fbthrift::TType::String, 1) => field_message = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (::fbthrift::TType::I32, 2) => field_error_code = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (fty, _) => p.skip(fty)?,
            }
            p.read_field_end()?;
        }
        p.read_struct_end()?;
        ::std::result::Result::Ok(Self {
            message: field_message.unwrap_or_default(),
            error_code: field_error_code.unwrap_or_default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        })
    }
}

#[allow(clippy::derivable_impls)]
impl ::std::default::Default for self::ExceptionWithStructuredAnnotation {
    fn default() -> Self {
        Self {
            message_field: ::std::default::Default::default(),
            error_code: ::std::default::Default::default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        }
    }
}

impl ::std::fmt::Debug for self::ExceptionWithStructuredAnnotation {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        formatter
            .debug_struct("ExceptionWithStructuredAnnotation")
            .field("message_field", &self.message_field)
            .field("error_code", &self.error_code)
            .finish()
    }
}

unsafe impl ::std::marker::Send for self::ExceptionWithStructuredAnnotation {}
unsafe impl ::std::marker::Sync for self::ExceptionWithStructuredAnnotation {}

impl ::fbthrift::GetTType for self::ExceptionWithStructuredAnnotation {
    const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
}

impl<P> ::fbthrift::Serialize<P> for self::ExceptionWithStructuredAnnotation
where
    P: ::fbthrift::ProtocolWriter,
{
    fn write(&self, p: &mut P) {
        p.write_struct_begin("ExceptionWithStructuredAnnotation");
        p.write_field_begin("message_field", ::fbthrift::TType::String, 1);
        ::fbthrift::Serialize::write(&self.message_field, p);
        p.write_field_end();
        p.write_field_begin("error_code", ::fbthrift::TType::I32, 2);
        ::fbthrift::Serialize::write(&self.error_code, p);
        p.write_field_end();
        p.write_field_stop();
        p.write_struct_end();
    }
}

impl<P> ::fbthrift::Deserialize<P> for self::ExceptionWithStructuredAnnotation
where
    P: ::fbthrift::ProtocolReader,
{
    fn read(p: &mut P) -> ::anyhow::Result<Self> {
        static FIELDS: &[::fbthrift::Field] = &[
            ::fbthrift::Field::new("error_code", ::fbthrift::TType::I32, 2),
            ::fbthrift::Field::new("message_field", ::fbthrift::TType::String, 1),
        ];
        let mut field_message_field = ::std::option::Option::None;
        let mut field_error_code = ::std::option::Option::None;
        let _ = p.read_struct_begin(|_| ())?;
        loop {
            let (_, fty, fid) = p.read_field_begin(|_| (), FIELDS)?;
            match (fty, fid as ::std::primitive::i32) {
                (::fbthrift::TType::Stop, _) => break,
                (::fbthrift::TType::String, 1) => field_message_field = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (::fbthrift::TType::I32, 2) => field_error_code = ::std::option::Option::Some(::fbthrift::Deserialize::read(p)?),
                (fty, _) => p.skip(fty)?,
            }
            p.read_field_end()?;
        }
        p.read_struct_end()?;
        ::std::result::Result::Ok(Self {
            message_field: field_message_field.unwrap_or_default(),
            error_code: field_error_code.unwrap_or_default(),
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        })
    }
}

#[allow(clippy::derivable_impls)]
impl ::std::default::Default for self::Banal {
    fn default() -> Self {
        Self {
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        }
    }
}

impl ::std::fmt::Debug for self::Banal {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        formatter
            .debug_struct("Banal")
            .finish()
    }
}

unsafe impl ::std::marker::Send for self::Banal {}
unsafe impl ::std::marker::Sync for self::Banal {}

impl ::fbthrift::GetTType for self::Banal {
    const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
}

impl<P> ::fbthrift::Serialize<P> for self::Banal
where
    P: ::fbthrift::ProtocolWriter,
{
    fn write(&self, p: &mut P) {
        p.write_struct_begin("Banal");
        p.write_field_stop();
        p.write_struct_end();
    }
}

impl<P> ::fbthrift::Deserialize<P> for self::Banal
where
    P: ::fbthrift::ProtocolReader,
{
    fn read(p: &mut P) -> ::anyhow::Result<Self> {
        static FIELDS: &[::fbthrift::Field] = &[
        ];
        let _ = p.read_struct_begin(|_| ())?;
        loop {
            let (_, fty, fid) = p.read_field_begin(|_| (), FIELDS)?;
            match (fty, fid as ::std::primitive::i32) {
                (::fbthrift::TType::Stop, _) => break,
                (fty, _) => p.skip(fty)?,
            }
            p.read_field_end()?;
        }
        p.read_struct_end()?;
        ::std::result::Result::Ok(Self {
            _dot_dot_Default_default: self::dot_dot::OtherFields(()),
        })
    }
}

mod dot_dot {
    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub struct OtherFields(pub(crate) ());

    #[allow(dead_code)] // if serde isn't being used
    pub(super) fn default_for_serde_deserialize() -> OtherFields {
        OtherFields(())
    }
}


text:
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.rules.proto;

import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.syntax.Type;

/** Implements {code proto_lang_toolchain}. */
public class ProtoLangToolchainRule implements RuleDefinition {
  @Override
  public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) {
    return builder

        /*
        This value will be passed to proto-compiler to generate the code. Only include the parts
        specific to this code-generator/plugin (e.g., do not include -I parameters)

$(OUT) is LANG_proto_library-specific. The rules are expected to define
              how they interpret this variable. For Java, for example, $(OUT) will be replaced with
              the src-jar filename to create.

$(PLUGIN_out) will be substituted to work with a
              `--plugin=protoc-gen-PLUGIN` command line.

         */
        .add(attr("command_line", Type.STRING).mandatory())

        /*
        If provided, will be made available to the action that calls the proto-compiler, and will be
        passed to the proto-compiler:
        --plugin=protoc-gen-PLUGIN=<executable>.
         */
        .add(attr("plugin", LABEL).exec().cfg(HOST).allowedFileTypes())

        /*
        A language-specific library that the generated code is compiled against.
        The exact behavior is LANG_proto_librar-specific.
        Java, for example, should compile against the runtime.
         */
        .add(attr("runtime", LABEL).allowedFileTypes())

        /*
        No code will be generated for files in the srcs attribute of
        blacklisted_protos.
        This is used for .proto files that are already linked into proto runtimes, such as
        any.proto.
         */
        .add(
            attr("blacklisted_protos", LABEL_LIST)
                .allowedFileTypes()
                .mandatoryNativeProviders(
                    ImmutableList.<Class<? extends TransitiveInfoProvider>>of(FileProvider.class)))
        .build();
  }

  @Override
  public Metadata getMetadata() {
    return RuleDefinition.Metadata.builder()
        .name("proto_lang_toolchain")
        .ancestors(BaseRuleClasses.RuleBase.class)
        .factoryClass(ProtoLangToolchain.class)
        .build();
  }
}

/*

Specifies how a LANG_proto_library rule (e.g., java_proto_library) should invoke the
proto-compiler.
Some LANG_proto_library rules allow specifying which toolchain to use using command-line flags;
consult their documentation.

Normally you should not write those kind of rules unless you want to
tune your Java compiler.

There's no compiler. The proto-compiler is taken from the proto_library rule we attach to. It is
passed as a command-line flag to Blaze.
Several features require a proto-compiler to be invoked on the proto_library rule itself.
It's beneficial to enforce the compiler that LANG_proto_library uses is the same as the one
proto_library does.

Examples

A simple example would be:

proto_lang_toolchain(
    name = "javalite_toolchain",
    command_line = "--$(PLUGIN_OUT)=shared,immutable:$(OUT)",
    plugin = ":javalite_plugin",
    runtime = ":protobuf_lite",
)

*/

redpajama_set_name: RedPajamaGithub


text:
<!doctype html>

    <title>Code coverage report for lib/waterline/core/index.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="../../../prettify.css" />
    <link rel="stylesheet" href="../../../base.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1">

      all files / lib/waterline/core/ index.js

        97.1%
        Statements
        67/69

        90.91%
        Branches
        40/44

        100%
        Functions
        5/5

        98.41%
        Lines
        62/63

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

3×
3×
3×
3×
3×
3×
3×
3×
3×
3×

3×

266×

266×
266×
266×

266×

266×
266×
266×

266×
266×
266×

266×

266×

266×

266×

3×
266×

266×

266×

266×

266×
266×
266×
266×

266×

266×
266×
263×

266×

266×
266×
266×

266×
1230×
259×

266×

266×

266×

266×
267×
267×

266×

3×

266×
9×

257×
254×

254×
58×

196×
196×

/**
 * Dependencies
 */

var _ = require('lodash');
var schemaUtils = require('../utils/schema');
var COLLECTION_DEFAULTS = require('../collection/defaults');
var Model = require('../model');
var Cast = require('./typecast');
var Schema = require('./schema');
var Dictionary = require('./dictionary');
var Validator = require('./validations');
var Transformer = require('./transformations');
var hasOwnProperty = require('../utils/helpers').object.hasOwnProperty;

/**
 * Core
 *
 * Setup the basic Core of a collection to extend.
 */

var Core = module.exports = function(options) {

  options = options || {};

  // Set Defaults
  this.adapter = this.adapter || {};
  this._attributes = this.attributes;
  this.connections = this.connections || {};

  this.defaults = _.merge(COLLECTION_DEFAULTS, this.defaults);

  // Construct our internal objects
  this._cast = new Cast();
  this._schema = new Schema(this);
  this._validator = new Validator();

  // Normalize attributes, extract instance methods, and callbacks
  // Note: this is ordered for a reason!
  this._callbacks = schemaUtils.normalizeCallbacks(this);
  this._instanceMethods = schemaUtils.instanceMethods(this.attributes);
  this._attributes = schemaUtils.normalizeAttributes(this._attributes);

  this.hasSchema = Core._normalizeSchemaFlag.call(this);

  this.migrate = Object.getPrototypeOf(this).hasOwnProperty('migrate') ?
    this.migrate : this.defaults.migrate;

  // Initalize the internal values from the Collection
  Core._initialize.call(this, options);

  return this;
};

/**
 * Initialize
 *
 * Setups internal mappings from an extended collection.
 */

Core._initialize = function(options) {
  var self = this;

  options = options || {};

  // Extend a base Model with instance methods
  this._model = new Model(this, this._instanceMethods);

  // Cache the attributes from the schema builder
  var schemaAttributes = this.waterline.schema[this.identity].attributes;

  // Remove auto attributes for validations
  var _validations = _.clone(this._attributes);
  if (this.autoPK) delete _validations.id;
  if (this.autoCreatedAt) delete _validations.createdAt;
  if (this.autoUpdatedAt) delete _validations.updatedAt;

  // If adapter exposes any reserved attributes, pass them to the schema
  var connIdx = Array.isArray(this.connection) ? this.connection[0] : this.connection;

  var adapterInfo = {};
  if (this.connections[connIdx] && this.connections[connIdx]._adapter) {
    adapterInfo = this.connections[connIdx]._adapter;
  }

  var reservedAttributes = adapterInfo.reservedAttributes || {};

  // Initialize internal objects from attributes
  this._schema.initialize(this._attributes, this.hasSchema, reservedAttributes);
  this._cast.initialize(this._schema.schema);
  this._validator.initialize(_validations, this.types, this.defaults.validations);

  // Set the collection's primaryKey attribute
  Object.keys(schemaAttributes).forEach(function(key) {
    if (hasOwnProperty(schemaAttributes[key], 'primaryKey') && schemaAttributes[key].primaryKey) {
      self.primaryKey = key;
    }
  });

  // Build Data Transformer
  this._transformer = new Transformer(schemaAttributes, this.waterline.schema);

  // Transform Schema
  this._schema.schema = this._transformer.serialize(this._schema.schema, 'schema');

  // Build up a dictionary of which methods run on which connection
  this.adapterDictionary = new Dictionary(_.cloneDeep(this.connections), this.connection);

  // Add this collection to the connection
  Object.keys(this.connections).forEach(function(conn) {
    self.connections[conn]._collections = self.connections[conn]._collections || [];
    self.connections[conn]._collections.push(self.identity);
  });

  // Remove remnants of user defined attributes
  delete this.attributes;
};

/**
 * Normalize Schema Flag
 *
 * Normalize schema setting by looking at the model first to see if it is defined, if not look at
 * the connection and see if it's defined and if not finally look into the adapter and check if
 * there is a default setting. If not found anywhere be safe and set to true.
 *
 * @api private
 * @return {Boolean}
 */

Core._normalizeSchemaFlag = function() {

  // If schema is defined on the collection, return the value
  if (hasOwnProperty(Object.getPrototypeOf(this), 'schema')) {
    return Object.getPrototypeOf(this).schema;
  }

  // Grab the first connection used
  if (!this.connection || !Array.isArray(this.connection)) return true;
  var connection = this.connections[this.connection[0]];

  // Check the user defined config
  if (hasOwnProperty(connection, 'config') && hasOwnProperty(connection.config, 'schema')) {
    return connection.config.schema;
  }

  // Check the defaults defined in the adapter
  Iif (!hasOwnProperty(connection, '_adapter')) return true;
  Eif (!hasOwnProperty(connection._adapter, 'schema')) return true;

  return connection._adapter.schema;
};

  Code coverage
  generated by istanbul at Fri Mar 18 2016 12:26:23 GMT-0500 (CDT)


text:
var Logger = require('../../connection/logger')
  , EventEmitter = require('events').EventEmitter
  , inherits = require('util').inherits
  , f = require('util').format;

/**
 * Creates a new Ping read preference strategy instance
 * @class
 * @param {object} [options.pingInterval=5000] Ping interval to check the response time to the different servers
 * @param {object} [options.acceptableLatency=250] Acceptable latency for selecting a server for reading (in milliseconds)
 * @return {Ping} A cursor instance
 */
var Ping = function(options) {
  // Add event listener
  EventEmitter.call(this);
  // Contains all the ping data
  var pings = {};

  // Set no options if none provided
  options = options || {};

  // Logger
  var logger = Logger('Ping', options);

  // Ping interval
  var pingInterval = options.pingInterval || 10000;
  var acceptableLatency = options.acceptableLatency || 15;

  // Debug options
  var debug = typeof options.debug == 'boolean' ? options.debug : false;

  // Index
  var index = 0;

  // Log the options set
  if(logger.isDebug()) logger.debug(f('ping strategy interval [%s], acceptableLatency [%s]', pingInterval, acceptableLatency));

  // Current ping time
  var lastPing = null;

  // If we have enabled debug
  if(debug) {
    // Add access to the read Preference Strategies
    Object.defineProperty(this, 'data', {
      enumerable: true, get: function() { return pings; }
    });
  }

  /**
   * Pick a server
   * @method
   * @param {State} set The current replicaset state object
   * @param {ReadPreference} readPreference The current readPreference object
   * @param {readPreferenceResultCallback} callback The callback to return the result from the function
   * @return {object}
   */
  this.pickServer = function(set, readPreference) {
    // Only get primary and secondaries as seeds
    var seeds = {};
    if(set.primary) seeds[set.primary.name] = true;
    for(var i = 0; i < set.secondaries.length; i++) {
      seeds[set.secondaries[i].name] = true;
    }

    // Transform the list
    var serverList = [];
    for(var name in seeds) {
      serverList.push({name: name, time: pings[name] || 0});
    }

    // Sort by time
    serverList.sort(function(a, b) {
      return a.time > b.time;
    });

    // Locate lowest time (picked servers are lowest time + acceptable Latency margin)
    var lowest = serverList.length > 0 ? serverList[0].time : 0;

    // Filter by latency
    serverList = serverList.filter(function(s) {
      return s.time <= lowest + acceptableLatency;
    });

    // No servers, default to primary
    if(serverList.length == 0 && set.primary) {
      if(logger.isInfo()) logger.info(f('picked primary server [%s]', set.primary.name));
      return set.primary;
    } else if(serverList.length == 0) {
      return null
    }

    // We picked first server
    if(logger.isInfo()) logger.info(f('picked server [%s] with ping latency [%s]', serverList[0].name, serverList[0].time));

    // Add to the index
    index = index + 1;
    // Select the index
    index = index % serverList.length;
    // Return the first server of the sorted and filtered list
    return set.get(serverList[index].name);
  }

  /**
   * Start of an operation
   * @method
   * @param {Server} server The server the operation is running against
   * @param {object} query The operation running
   * @param {Date} date The start time of the operation
   * @return {object}
   */
  this.startOperation = function(server, query, date) {
  }

  /**
   * End of an operation
   * @method
   * @param {Server} server The server the operation is running against
   * @param {error} err An error from the operation
   * @param {object} result The result from the operation
   * @param {Date} date The start time of the operation
   * @return {object}
   */
  this.endOperation = function(server, err, result, date) {
  }

  /**
   * High availability process running
   * @method
   * @param {State} set The current replicaset state object
   * @param {resultCallback} callback The callback to return the result from the function
   * @return {object}
   */
  this.ha = function(topology, state, callback) {
    var self = this;
    var servers = state.getAll();
    var count = servers.length;

    // No servers return
    if(servers.length == 0) return callback(null, null);

    // Return if we have not yet reached the ping interval
    if(lastPing != null) {
      var diff = new Date().getTime() - lastPing.getTime();
      if(diff < pingInterval) return callback(null, null);
    }

    // Execute operation
    var operation = function(_server) {
      var start = new Date();
      // Execute ping against server
      _server.command('system.$cmd', {ismaster:1}, function(err, r) {
        count = count - 1;
        var time = new Date().getTime() - start.getTime();
        pings[_server.name] = time;
        // Log info for debug
        if(logger.isDebug()) logger.debug(f('ha latency for server [%s] is [%s] ms', _server.name, time));
        // We are done with all the servers
        if(count == 0) {
          // Emit ping event
          topology.emit('ping', err, r ? r.result : null);
          // Update the last ping time
          lastPing = new Date();
          // Return
          callback(null, null);
        }
      });
    }

    // Let's ping all servers
    while(servers.length > 0) {
      operation(servers.shift());
    }
  }

  var removeServer = function(server) {
    delete pings[server.name];
  }

  /**
   * Server connection closed
   * @method
   * @param {Server} server The server that closed
   */
  this.close = function(server) {
    removeServer(server);
  }

  /**
   * Server connection errored out
   * @method
   * @param {Server} server The server that errored out
   */
  this.error = function(server) {
    removeServer(server);
  }

  /**
   * Server connection timeout
   * @method
   * @param {Server} server The server that timed out
   */
  this.timeout = function(server) {
    removeServer(server);
  }

  /**
   * Server connection happened
   * @method
   * @param {Server} server The server that connected
   * @param {resultCallback} callback The callback to return the result from the function
   */
  this.connect = function(server, callback) {
    // Get the command start date
    var start = new Date();
    // Execute ping against server
    server.command('system.$cmd', {ismaster:1}, function(err, r) {
      var time = new Date().getTime() - start.getTime();
      pings[server.name] = time;
      // Log info for debug
      if(logger.isDebug()) logger.debug(f('connect latency for server [%s] is [%s] ms', server.name, time));
      // Set last ping
      lastPing = new Date();
      // Done, return
      callback(null, null);
    });
  }
}

inherits(Ping, EventEmitter);

/**
 * This is a result from a readPreference strategy
 *
 * @callback readPreferenceResultCallback
 * @param {error} error An error object. Set to null if no error present
 * @param {Server} server The server picked by the strategy
 */

module.exports = Ping;


text:
package com.android.tools.idea.sdk.remote.internal.updater;

import com.android.annotations.NonNull;
import com.android.annotations.VisibleForTesting;
import com.android.annotations.VisibleForTesting.Visibility;
import com.android.sdklib.SdkManager;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.repository.ISdkChangeListener;
import com.android.sdklib.repository.License;
import com.android.sdklib.util.LineUtil;
import com.android.tools.idea.sdk.SdkState;
import com.android.tools.idea.sdk.remote.RemotePkgInfo;
import com.android.tools.idea.sdk.remote.UpdatablePkgInfo;
import com.android.tools.idea.sdk.remote.internal.*;
import com.android.tools.idea.sdk.remote.internal.archives.Archive;
import com.android.tools.idea.sdk.remote.internal.archives.ArchiveInstaller;
import com.android.tools.idea.sdk.remote.internal.packages.RemoteAddonPkgInfo;
import com.android.tools.idea.sdk.remote.internal.packages.PlatformToolRemotePkgInfo;
import com.android.tools.idea.sdk.remote.internal.packages.RemoteToolPkgInfo;
import com.android.tools.idea.sdk.remote.internal.sources.SdkRepoConstants;
import com.android.tools.idea.sdk.remote.internal.sources.SdkRepoSource;
import com.android.tools.idea.sdk.remote.internal.sources.SdkSourceCategory;
import com.android.tools.idea.sdk.remote.internal.sources.SdkSources;
import com.android.utils.ILogger;
import com.android.utils.IReaderLogger;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.android.sdk.AndroidSdkUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.*;

/**
 * Data shared by the SDK Manager updaters.
 */
public class UpdaterData implements IUpdaterData {

  public static final int NO_TOOLS_MSG = 0;
  public static final int TOOLS_MSG_UPDATED_FROM_ADT = 1;
  public static final int TOOLS_MSG_UPDATED_FROM_SDKMAN = 2;

  private String mOsSdkRoot;

  /**
   * Holds all sources. Do not use this directly.
   * Instead use {@link #getSources()} so that unit tests can override this as needed.
   */
  private final SdkSources mSources = new SdkSources();
  /**
   * Holds settings. Do not use this directly.
   * Instead use {@link #getSettingsController()} so that unit tests can override this.
   */
  private final SettingsController mSettingsController;
  private final ArrayList<ISdkChangeListener> mListeners = new ArrayList<ISdkChangeListener>();
  private final ILogger mSdkLog;
  private ITaskFactory mTaskFactory;

  private SdkManager mSdkManager;
  /**
   * The current {@link DownloadCache} to use.
   * Lazily created in {@link #getDownloadCache()}.
   */
  private DownloadCache mDownloadCache;

  /**
   * Creates a new updater data.
   *
   * @param sdkLog    Logger. Cannot be null.
   * @param osSdkRoot The OS path to the SDK root.
   */
  public UpdaterData(String osSdkRoot, ILogger sdkLog) {
    mOsSdkRoot = osSdkRoot;
    mSdkLog = sdkLog;

    mSettingsController = initSettingsController();
    initSdk();
  }

  // ----- getters, setters ----

  public String getOsSdkRoot() {
    return mOsSdkRoot;
  }

  @Override
  public DownloadCache getDownloadCache() {
    if (mDownloadCache == null) {
      mDownloadCache = new DownloadCache(
        getSettingsController().getSettings().getUseDownloadCache() ? DownloadCache.Strategy.FRESH_CACHE : DownloadCache.Strategy.DIRECT);
    }
    return mDownloadCache;
  }

  public void setTaskFactory(ITaskFactory taskFactory) {
    mTaskFactory = taskFactory;
  }

  @Override
  public ITaskFactory getTaskFactory() {
    return mTaskFactory;
  }

  public SdkSources getSources() {
    return mSources;
  }

  @Override
  public ILogger getSdkLog() {
    return mSdkLog;
  }

  @Override
  public SdkManager getSdkManager() {
    return mSdkManager;
  }

  @Override
  public SettingsController getSettingsController() {
    return mSettingsController;
  }

  /**
   * Removes a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded.
   */
  public void removeListener(ISdkChangeListener listener) {
    mListeners.remove(listener);
  }

  protected void displayInitError(String error) {
    mSdkLog.error(null /* Throwable */, "%s", error);  //$NON-NLS-1$
  }

  // -----

  /**
   * Runs a runnable on the UI thread.
   * The base implementation just runs the runnable right away.
   *
   * @param r Non-null runnable.
   */
  protected void runOnUiThread(@NonNull Runnable r) {
    r.run();
  }

  /**
   * Initializes the {@link SdkManager} and the {@link AvdManager}.
   * Extracted so that we can override this in unit tests.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected void initSdk() {
    setSdkManager(SdkManager.createManager(mOsSdkRoot, mSdkLog));
    // notify listeners.
    broadcastOnSdkReload();
  }

  /**
   * Initializes the {@link SettingsController}
   * Extracted so that we can override this in unit tests.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected SettingsController initSettingsController() {
    SettingsController settingsController = new SettingsController(mSdkLog);
    return settingsController;
  }

  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected void setSdkManager(SdkManager sdkManager) {
    mSdkManager = sdkManager;
  }

  /**
   * Reloads the SDK content (targets).
   *

   * This also reloads the AVDs in case their status changed.
   *

   * This does not notify the listeners ({@link ISdkChangeListener}).
   */
  public void reloadSdk() {
    // reload SDK
    mSdkManager.reloadSdk(mSdkLog);

    // notify listeners
    broadcastOnSdkReload();
  }

  /**
   * Sets up the default sources:

   * - the default google SDK repository,

   * - the user sources from prefs

   * - the extra repo URLs from the environment,

   * - and finally the extra user repo URLs from the environment.
   */
  public void setupDefaultSources() {
    SdkSources sources = getSources();

    // Load the conventional sources.
    // For testing, the env var can be set to replace the default root download URL.
    // It must end with a / and its the location where the updater will look for
    // the repository.xml, addons_list.xml and such files.

    String baseUrl = System.getenv("SDK_TEST_BASE_URL");                        //$NON-NLS-1$
    if (baseUrl == null || baseUrl.length() <= 0 || !baseUrl.endsWith("/")) {   //$NON-NLS-1$
      baseUrl = SdkRepoConstants.URL_GOOGLE_SDK_SITE;
    }

    sources.add(SdkSourceCategory.ANDROID_REPO, new SdkRepoSource(baseUrl, SdkSourceCategory.ANDROID_REPO.getUiName()));

    // Load user sources (this will also notify change listeners but this operation is
    // done early enough that there shouldn't be any anyway.)
    sources.loadUserAddons(getSdkLog());
  }

  /**
   * Install the list of given {@link Archive}s. This is invoked by the user selecting some
   * packages in the remote page and then clicking "install selected".
   *
   * @param archives The archives to install. Incompatible ones will be skipped.
   * @param flags    Optional flags for the installer, such as {@link #NO_TOOLS_MSG}.
   * @return A list of archives that have been installed. Can be empty but not null.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected List<Archive> installArchives(final List<ArchiveInfo> archives, final int flags) {
    if (mTaskFactory == null) {
      throw new IllegalArgumentException("Task Factory is null");
    }

    // this will accumulate all the packages installed.
    final List<Archive> newlyInstalledArchives = new ArrayList<Archive>();

    final boolean forceHttp = getSettingsController().getSettings().getForceHttp();

    // sort all archives based on their dependency level.
    Collections.sort(archives, new InstallOrderComparator());

    mTaskFactory.start("Installing Archives", new ITask() {
      @Override
      public void run(ITaskMonitor monitor) {

        final int progressPerArchive = 2 * ArchiveInstaller.NUM_MONITOR_INC;
        monitor.setProgressMax(1 + archives.size() * progressPerArchive);
        monitor.setDescription("Preparing to install archives");

        boolean installedAddon = false;
        boolean installedTools = false;
        boolean installedPlatformTools = false;
        boolean preInstallHookInvoked = false;

        int numInstalled = 0;
        nextArchive:
        for (ArchiveInfo ai : archives) {
          Archive archive = ai.getNewArchive();
          if (archive == null) {
            // This is not supposed to happen.
            continue nextArchive;
          }

          int nextProgress = monitor.getProgress() + progressPerArchive;
          try {
            if (monitor.isCancelRequested()) {
              break;
            }

            ArchiveInfo[] adeps = ai.getDependsOn();
            if (adeps != null) {
              for (ArchiveInfo adep : adeps) {
                Archive na = adep.getNewArchive();
                if (na == null) {
                  // This archive depends on a missing archive.
                  // We shouldn't get here.
                  // Skip it.
                  monitor.log("Skipping '%1$s'; it depends on a missing package.", archive.getParentPackage().getShortDescription());
                  continue nextArchive;
                }
              }
            }

            if (!preInstallHookInvoked) {
              preInstallHookInvoked = true;
              broadcastPreInstallHook();
            }

            ArchiveInstaller installer = createArchiveInstaler();
            if (installer.install(ai, mOsSdkRoot, forceHttp, mSdkManager, getDownloadCache(), monitor)) {
              // We installed this archive.
              newlyInstalledArchives.add(archive);
              numInstalled++;

              // Check if we successfully installed a platform-tool or add-on package.
              if (archive.getParentPackage() instanceof RemoteAddonPkgInfo) {
                installedAddon = true;
              }
              else if (archive.getParentPackage() instanceof RemoteToolPkgInfo) {
                installedTools = true;
              }
              else if (archive.getParentPackage() instanceof PlatformToolRemotePkgInfo) {
                installedPlatformTools = true;
              }
            }

          }
          catch (Throwable t) {
            // Display anything unexpected in the monitor.
            String msg = t.getMessage();
            if (msg != null) {
              msg = String.format("Unexpected Error installing '%1$s': %2$s: %3$s", archive.getParentPackage().getShortDescription(),
                                  t.getClass().getCanonicalName(), msg);
            }
            else {
              // no error info? get the stack call to display it
              // At least that'll give us a better bug report.
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              t.printStackTrace(new PrintStream(baos));

              msg = String
                .format("Unexpected Error installing '%1$s'\n%2$s", archive.getParentPackage().getShortDescription(), baos.toString());
            }

            monitor.log("%1$s", msg);      //$NON-NLS-1$
            mSdkLog.error(t, "%1$s", msg);      //$NON-NLS-1$
          }
          finally {

            // Always move the progress bar to the desired position.
            // This allows internal methods to not have to care in case
            // they abort early
            monitor.incProgress(nextProgress - monitor.getProgress());
          }
        }

        if (installedAddon) {
          // Update the USB vendor ids for adb
          try {
            mSdkManager.updateAdb();
            monitor.log("Updated ADB to support the USB devices declared in the SDK add-ons.");
          }
          catch (Exception e) {
            mSdkLog.error(e, "Update ADB failed");
            monitor.logError("failed to update adb to support the USB devices declared in the SDK add-ons.");
          }
        }

        if (preInstallHookInvoked) {
          broadcastPostInstallHook();
        }

        if (installedAddon || installedPlatformTools) {
          // We need to restart ADB. Actually since we don't know if it's even
          // running, maybe we should just kill it and not start it.
          // Note: it turns out even under Windows we don't need to kill adb
          // before updating the tools folder, as adb.exe is (surprisingly) not
          // locked.

          askForAdbRestart(monitor);
        }

        if (installedTools) {
          notifyToolsNeedsToBeRestarted(flags);
        }

        if (numInstalled == 0) {
          monitor.setDescription("Done. Nothing was installed.");
        }
        else {
          monitor.setDescription("Done. %1$d %2$s installed.", numInstalled, numInstalled == 1 ? "package" : "packages");

          //notify listeners something was installed, so that they can refresh
          reloadSdk();
        }
      }
    });

    return newlyInstalledArchives;
  }

  /**
   * A comparator to sort all the {@link ArchiveInfo} based on their
   * dependency level. This forces the installer to install first all packages
   * with no dependency, then those with one level of dependency, etc.
   */
  private static class InstallOrderComparator implements Comparator<ArchiveInfo> {

    private final Map<ArchiveInfo, Integer> mOrders = new HashMap<ArchiveInfo, Integer>();

    @Override
    public int compare(ArchiveInfo o1, ArchiveInfo o2) {
      int n1 = getDependencyOrder(o1);
      int n2 = getDependencyOrder(o2);

      return n1 - n2;
    }

    private int getDependencyOrder(ArchiveInfo ai) {
      if (ai == null) {
        return 0;
      }

      // reuse cached value, if any
      Integer cached = mOrders.get(ai);
      if (cached != null) {
        return cached.intValue();
      }

      ArchiveInfo[] deps = ai.getDependsOn();
      if (deps == null) {
        return 0;
      }

      // compute dependencies, recursively
      int n = deps.length;

      for (ArchiveInfo dep : deps) {
        n += getDependencyOrder(dep);
      }

      // cache it
      mOrders.put(ai, Integer.valueOf(n));

      return n;
    }

  }

  /**
   * Attempts to restart ADB.
   *

   * If the "ask before restart" setting is set (the default), prompt the user whether
   * now is a good time to restart ADB.
   */
  protected void askForAdbRestart(ITaskMonitor monitor) {
    // Restart ADB if we don't need to ask.
    if (!getSettingsController().getSettings().getAskBeforeAdbRestart()) {
      AdbWrapper adb = new AdbWrapper(getOsSdkRoot(), monitor);
      adb.stopAdb();
      adb.startAdb();
    }
  }

  protected void notifyToolsNeedsToBeRestarted(int flags) {

    String msg = null;
    if ((flags & TOOLS_MSG_UPDATED_FROM_ADT) == TOOLS_MSG_UPDATED_FROM_ADT) {
      msg = "The Android SDK and AVD Manager that you are currently using has been updated. " +
            "Please also run Eclipse > Help > Check for Updates to see if the Android " +
            "plug-in needs to be updated.";

    }
    else if ((flags & TOOLS_MSG_UPDATED_FROM_SDKMAN) == TOOLS_MSG_UPDATED_FROM_SDKMAN) {
      msg = "The Android SDK and AVD Manager that you are currently using has been updated. " +
            "It is recommended that you now close the manager window and re-open it. " +
            "If you use Eclipse, please run Help > Check for Updates to see if the Android " +
            "plug-in needs to be updated.";
    }
    else if ((flags & NO_TOOLS_MSG) == NO_TOOLS_MSG) {
      return;
    }
    mSdkLog.info("%s", msg);  //$NON-NLS-1$
  }

  /**
   * Tries to update all the *existing* local packages.
   * This version is intended to run without a GUI and
   * only outputs to the current {@link ILogger}.
   *
   * @param pkgFilter           A list of {@link SdkRepoConstants#NODES} or {@link Package#installId()}
   *                            or package indexes to limit the packages we can update or install.
   *                            A null or empty list means to update everything possible.
   * @param includeAll          True to list and install all packages, including obsolete ones.
   * @param dryMode             True to check what would be updated/installed but do not actually
   *                            download or install anything.
   * @param acceptLicense       SDK licenses to automatically accept.
   * @param includeDependencies If true, also include any required dependencies
   * @return A list of archives that have been installed. Can be null if nothing was done.
   */
  public List<Archive> updateOrInstallAll_NoGUI(Collection<String> pkgFilter,
                                                boolean includeAll,
                                                boolean dryMode,
                                                String acceptLicense,
                                                boolean includeDependencies) {

    List<ArchiveInfo> archives = getRemoteArchives(includeAll);

    // Filter the selected archives to only keep the ones matching the filter
    if (pkgFilter != null && pkgFilter.size() > 0 && archives != null && archives.size() > 0) {
      // Prepare a map install-id => package instance
      HashSet<String> installIds = new HashSet<String>();
      for (ArchiveInfo ai : archives) {
        Archive a = ai.getNewArchive();
        if (a != null) {
          RemotePkgInfo p = a.getParentPackage();
          if (p != null) {
            String iid = p.installId().toLowerCase(Locale.US);
            if (iid.length() > 0 && !installIds.contains(iid)) {
              installIds.add(iid);
            }
          }
        }
      }

      // Now intersect this with the pkgFilter requested by the user, in order to
      // only keep the classes that the user wants to install.
      // We also create a set with the package indices requested by the user
      // and a set of install-ids requested by the user.

      Set<String> userFilteredInstallIds = new HashSet<String>();

      for (String iid : pkgFilter) {
        // The install-id is not case-sensitive.
        iid = iid.toLowerCase(Locale.US);

        if (installIds.contains(iid)) {
          userFilteredInstallIds.add(iid);

        }
        else {
          // This should not happen unless there's a mismatch in the package map.
          mSdkLog.error(null, "Ignoring unknown package filter '%1$s'", iid);
        }
      }

      // Now filter the remote archives list to keep:
      // - any package which class matches userFilteredClasses
      // - any package index which matches userFilteredIndices
      // - any package install id which matches userFilteredInstallIds

      for (Iterator<ArchiveInfo> it = archives.iterator(); it.hasNext(); ) {
        boolean keep = false;
        ArchiveInfo ai = it.next();
        Archive a = ai.getNewArchive();
        if (a != null) {
          RemotePkgInfo p = a.getParentPackage();
          if (p != null) {
            if (userFilteredInstallIds.contains(p.installId().toLowerCase(Locale.US))) {
              keep = true;
            }
          }
        }

        if (!keep) {
          it.remove();
        }
      }

      if (archives.isEmpty()) {
        mSdkLog.info(LineUtil.reflowLine(
          "Warning: The package filter removed all packages. There is nothing to install.\nPlease consider trying to update again without a package filter.\n"));
        return null;
      }
    }

    if (archives != null && !archives.isEmpty()) {
      if (includeDependencies) {
        List<ArchiveInfo> dependencies = getDependencies(archives);
        if (!dependencies.isEmpty()) {
          List<ArchiveInfo> combined = Lists.newArrayList();
          combined.addAll(dependencies);
          combined.addAll(archives);
          archives = combined;
        }
      }
      if (dryMode) {
        mSdkLog.info("Packages selected for install:\n");
        for (ArchiveInfo ai : archives) {
          Archive a = ai.getNewArchive();
          if (a != null) {
            RemotePkgInfo p = a.getParentPackage();
            if (p != null) {
              mSdkLog.info("- %1$s\n", p.getShortDescription());
            }
          }
        }
        mSdkLog.info("\nDry mode is on so nothing is actually being installed.\n");
      }
      else {
        if (acceptLicense(archives, acceptLicense, 100 /* numRetries */)) {
          return installArchives(archives, NO_TOOLS_MSG);
        }
      }
    }
    else {
      mSdkLog.info("There is nothing to install or update.\n");
    }

    return null;
  }

  private List<ArchiveInfo> getRemoteArchives(boolean includeAll) {
    SdkState state = SdkState.getInstance(AndroidSdkUtils.tryToChooseAndroidSdk());
    state.loadSynchronously(SdkState.DEFAULT_EXPIRATION_PERIOD_MS, false, null, null, null, false);
    List<ArchiveInfo> result = Lists.newArrayList();
    for (UpdatablePkgInfo update : state.getPackages().getConsolidatedPkgs().values()) {
      for (RemotePkgInfo remote : update.getAllRemotes()) {
        if (includeAll || !remote.isObsolete()) {
          for (Archive archive : remote.getArchives()) {
            if (archive.isCompatible()) {
              result.add(new ArchiveInfo(archive, update.getLocalInfo(), null));
            }
          }
        }
      }
    }
    return result;
  }

  /**
   * Computes the transitive dependencies of the given list of archives. This will only
   * include dependencies that also need to be installed, not satisfied dependencies.
   */
  private static List<ArchiveInfo> getDependencies(@NonNull List<ArchiveInfo> archives) {
    List<ArchiveInfo> dependencies = Lists.newArrayList();
    for (ArchiveInfo archive : archives) {
      addDependencies(dependencies, archive, Sets.<ArchiveInfo>newHashSet());
    }
    return dependencies;
  }

  private static void addDependencies(@NonNull List<ArchiveInfo> dependencies,
                                      @NonNull ArchiveInfo archive,
                                      @NonNull Set<ArchiveInfo> visited) {
    if (visited.contains(archive)) {
      return;
    }
    visited.add(archive);

    ArchiveInfo[] dependsOn = archive.getDependsOn();
    if (dependsOn != null) {
      for (ArchiveInfo dependency : dependsOn) {
        if (!dependencies.contains(dependency)) {
          dependencies.add(dependency);
          addDependencies(dependencies, dependency, visited);
        }
      }
    }
  }

  /**
   * Validates that all archive licenses are accepted.
   *

   * There are 2 cases:

   * - When {@code acceptLicenses} is given, the licenses specified are automatically
   * accepted and all those not specified are automatically rejected.

   * - When {@code acceptLicenses} is empty or null, licenses are collected and there's
   * an input prompt on StdOut to ask a yes/no question. To output, this uses the
   * current {@link #mSdkLog} which should be configured to send
   * {@link ILogger#info(String, Object...)} directly to {@link System#out}.

   *

   * Finally only accepted licenses are kept in the archive list.
   *
   * @param archives         The archives to validate.
   * @param acceptLicenseIds A comma-separated list of licenses ids already approved.
   * @param numRetries       The number of times the command-line will ask to accept a given
   *                         license when the input doesn't match the expected y/n/yes/no answer.
   *                         Use 0 for infinite. Useful for unit-tests. Once the number of retries
   *                         is reached, the license is assumed as rejected.
   * @return True if there are any archives left to install.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  boolean acceptLicense(List<ArchiveInfo> archives, String acceptLicenseIds, final int numRetries) {
    TreeSet<String> acceptedLids = new TreeSet<String>();
    if (acceptLicenseIds != null) {
      acceptedLids.addAll(Arrays.asList(acceptLicenseIds.split(",")));  //$NON-NLS-1$
    }
    boolean automated = !acceptedLids.isEmpty();

    TreeSet<String> rejectedLids = new TreeSet<String>();
    TreeMap<String, License> lidToAccept = new TreeMap<String, License>();
    TreeMap<String, List<String>> lidPkgNames = new TreeMap<String, List<String>>();

    // Find the licenses needed. Include those already accepted.
    for (ArchiveInfo ai : archives) {
      License lic = getArchiveInfoLicense(ai);
      if (lic == null) {
        continue;
      }
      String lid = getLicenseId(lic);
      if (!acceptedLids.contains(lid)) {
        if (automated) {
          // Automatically reject those not already accepted
          rejectedLids.add(lid);
        }
        else {
          // Queue it to ask for it to be accepted
          lidToAccept.put(lid, lic);
          List<String> list = lidPkgNames.get(lid);
          if (list == null) {
            list = new ArrayList<String>();
            lidPkgNames.put(lid, list);
          }
          list.add(ai.getShortDescription());
        }
      }
    }

    // Ask for each license that needs to be asked manually for confirmation
    nextEntry:
    for (Map.Entry<String, License> entry : lidToAccept.entrySet()) {
      String lid = entry.getKey();
      License lic = entry.getValue();
      mSdkLog.info("-------------------------------\n");
      mSdkLog.info("License id: %1$s\n", lid);
      mSdkLog.info("Used by: \n - %1$s\n", Joiner.on("\n  - ").skipNulls().join(lidPkgNames.get(lid)));
      mSdkLog.info("-------------------------------\n\n");
      mSdkLog.info("%1$s\n", lic.getLicense());

      int retries = numRetries;
      tryAgain:
      while (true) {
        try {
          mSdkLog.info("Do you accept the license '%1$s' [y/n]: ", lid);

          byte[] buffer = new byte[256];
          if (mSdkLog instanceof IReaderLogger) {
            ((IReaderLogger)mSdkLog).readLine(buffer);
          }
          else {
            System.in.read(buffer);
          }
          mSdkLog.info("\n");

          String reply = new String(buffer, Charsets.UTF_8);
          reply = reply.trim().toLowerCase(Locale.US);

          if ("y".equals(reply) || "yes".equals(reply)) {
            acceptedLids.add(lid);
            continue nextEntry;

          }
          else if ("n".equals(reply) || "no".equals(reply)) {
            break tryAgain;

          }
          else {
            mSdkLog.info("Unknown response '%1$s'.\n", reply);
            if (--retries == 0) {
              mSdkLog.info("Max number of retries exceeded. Rejecting '%1$s'\n", lid);
              break tryAgain;
            }
            continue tryAgain;
          }

        }
        catch (IOException e) {
          // Panic. Don't install anything.
          e.printStackTrace();
          return false;
        }
      }
      rejectedLids.add(lid);
    }

    // Finally remove all archive which license is rejected or not accepted.
    for (Iterator<ArchiveInfo> it = archives.iterator(); it.hasNext(); ) {
      ArchiveInfo ai = it.next();
      License lic = getArchiveInfoLicense(ai);
      if (lic == null) {
        continue;
      }
      String lid = getLicenseId(lic);
      if (rejectedLids.contains(lid) || !acceptedLids.contains(lid)) {
        mSdkLog.info("Package %1$s not installed due to rejected license '%2$s'.\n", ai.getShortDescription(), lid);
        it.remove();
      }
    }

    return !archives.isEmpty();
  }

  private License getArchiveInfoLicense(ArchiveInfo ai) {
    Archive a = ai.getNewArchive();
    if (a != null) {
      RemotePkgInfo p = a.getParentPackage();
      if (p != null) {
        License lic = p.getLicense();
        if (lic != null &&
            lic.getLicenseRef() != null &&
            lic.getLicense().length() > 0 &&
            lic.getLicense() != null &&
            lic.getLicense().length() > 0) {
          return lic;
        }
      }
    }

    return null;
  }

  private String getLicenseId(License lic) {
    return String.format("%1$s-%2$08x",       //$NON-NLS-1$
                         lic.getLicenseRef(), lic.getLicense().hashCode());
  }

  /**
   * Safely invoke all the registered {@link ISdkChangeListener#onSdkReload()}.
   * This can be called from any thread.
   */
  private void broadcastOnSdkReload() {
    if (mListeners.size() > 0) {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          for (ISdkChangeListener listener : mListeners) {
            try {
              listener.onSdkReload();
            }
            catch (Throwable t) {
              mSdkLog.error(t, null);
            }
          }
        }
      });
    }
  }

  /**
   * Safely invoke all the registered {@link ISdkChangeListener#preInstallHook()}.
   * This can be called from any thread.
   */
  private void broadcastPreInstallHook() {
    if (mListeners.size() > 0) {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          for (ISdkChangeListener listener : mListeners) {
            try {
              listener.preInstallHook();
            }
            catch (Throwable t) {
              mSdkLog.error(t, null);
            }
          }
        }
      });
    }
  }

  /**
   * Safely invoke all the registered {@link ISdkChangeListener#postInstallHook()}.
   * This can be called from any thread.
   */
  private void broadcastPostInstallHook() {
    if (mListeners.size() > 0) {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          for (ISdkChangeListener listener : mListeners) {
            try {
              listener.postInstallHook();
            }
            catch (Throwable t) {
              mSdkLog.error(t, null);
            }
          }
        }
      });
    }
  }

  /**
   * Internal helper to return a new {@link ArchiveInstaller}.
   * This allows us to override the installer for unit-testing.
   */
  @VisibleForTesting(visibility = Visibility.PRIVATE)
  protected ArchiveInstaller createArchiveInstaler() {
    return new ArchiveInstaller();
  }
}