{{!

  Copyright (c) Facebook, Inc. and its affiliates.

  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.

}}

    {{#service:interactions}}{{>lib/service}}
    {{/service:interactions}}
    pub mod {{service:snake}} {{>lib/block}}{{!
        }}{{#service:docs?}}
        #![doc = {{service:docs}}]
        {{/service:docs?}}{{!
        }}{{#service:rustFunctions}}{{^function:starts_interaction?}}{{#function:returns_stream?}}

        #[derive(Clone, Debug)]
        pub enum {{function:upcamel}}StreamExn {
            Success({{#function:return_type}}{{#type:stream_elem_type}}{{>lib/type}}{{/type:stream_elem_type}}{{/function:return_type}}),{{!
            }}{{#function:stream_exceptions}}
            {{field:rust_name}}({{#field:type}}{{>lib/type}}{{/field:type}}),{{!
            }}{{/function:stream_exceptions}}
            ApplicationException(::fbthrift::ApplicationException),
        }{{!
        }}{{#function:uniqueStreamExceptions}}

        impl ::fbthrift::ExceptionInfo for {{function:upcamel}}StreamExn {
            fn exn_name(&self) -> &'static str {
                match self {
                    {{function:upcamel}}StreamExn::Success(_) => panic!("ExceptionInfo::exn_name called on Success"),
                    {{function:upcamel}}StreamExn::ApplicationException(aexn) => aexn.exn_name(),
                    {{#function:stream_exceptions}}
                    {{function:upcamel}}StreamExn::{{field:rust_name}}(exn) => exn.exn_name(),
                    {{/function:stream_exceptions}}
                }
            }

            fn exn_value(&self) -> String {
                match self {
                    {{function:upcamel}}StreamExn::Success(_) => panic!("ExceptionInfo::exn_value called on Success"),
                    {{function:upcamel}}StreamExn::ApplicationException(aexn) => aexn.exn_value(),
                    {{#function:stream_exceptions}}
                    {{function:upcamel}}StreamExn::{{field:rust_name}}(exn) => exn.exn_value(),
                    {{/function:stream_exceptions}}
                }
            }

            fn exn_is_declared(&self) -> bool {
                match self {
                    {{function:upcamel}}StreamExn::Success(_) => panic!("ExceptionInfo::exn_is_declared called on Success"),
                    {{function:upcamel}}StreamExn::ApplicationException(aexn) => aexn.exn_is_declared(),
                    {{#function:stream_exceptions}}
                    {{function:upcamel}}StreamExn::{{field:rust_name}}(exn) => exn.exn_is_declared(),
                    {{/function:stream_exceptions}}
                }
            }
        }

        impl ::fbthrift::ResultInfo for {{function:upcamel}}StreamExn {
            fn result_type(&self) -> ::fbthrift::ResultType {
                match self {
                    {{function:upcamel}}StreamExn::Success(_) => ::fbthrift::ResultType::Return,
                    {{function:upcamel}}StreamExn::ApplicationException(_aexn) => ::fbthrift::ResultType::Exception,
                    {{#function:exceptions}}
                    {{function:upcamel}}StreamExn::{{field:rust_name}}(_exn) => fbthrift::ResultType::Error,
                    {{/function:exceptions}}
                }
            }
        }

        impl ::std::convert::From<{{#field:type}}{{>lib/type}}{{/field:type}}> for {{function:upcamel}}StreamExn {
            fn from(exn: {{#field:type}}{{>lib/type}}{{/field:type}}) -> Self {
                {{function:upcamel}}StreamExn::{{field:rust_name}}(exn)
            }
        }{{!
        }}{{/function:uniqueStreamExceptions}}

        impl ::std::convert::From<::fbthrift::ApplicationException> for {{function:upcamel}}StreamExn {
            fn from(exn: ::fbthrift::ApplicationException) -> Self {
                {{function:upcamel}}StreamExn::ApplicationException(exn)
            }
        }

        impl ::fbthrift::GetTType for {{function:upcamel}}StreamExn {
            const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
        }

        impl<P> ::fbthrift::Serialize<P> for {{function:upcamel}}StreamExn
        where
            P: ::fbthrift::ProtocolWriter,
        {
            fn write(&self, p: &mut P) {
                p.write_struct_begin("{{function:upcamel}}");
                match self {
                    {{function:upcamel}}StreamExn::Success(inner) => {
                        p.write_field_begin(
                            "Success",
                            {{#function:return_type}}{{>lib/ttype}}{{/function:return_type}},
                            0i16,
                        );
                        inner.write(p);
                        p.write_field_end();
                    }{{!
                    }}{{#function:stream_exceptions}}
                    {{function:upcamel}}StreamExn::{{field:rust_name}}(inner) => {
                        p.write_field_begin(
                            "{{field:name}}",
                            {{#field:type}}{{>lib/ttype}}{{/field:type}},
                            {{field:key}},
                        );
                        inner.write(p);
                        p.write_field_end();
                    }{{!
                    }}{{/function:stream_exceptions}}
                    {{function:upcamel}}StreamExn::ApplicationException(_) => panic!(
                        "Bad union Alt field {} id {}",
                        "ApplicationException",
                        -2147483648i32,
                    ),
                }
                p.write_field_stop();
                p.write_struct_end();
            }
        }

        impl<P> ::fbthrift::Deserialize<P> for {{function:upcamel}}StreamExn
        where
            P: ::fbthrift::ProtocolReader,
        {
            fn read(p: &mut P) -> ::anyhow::Result<Self> {
                static RETURNS: &[::fbthrift::Field] = &[
                    {{#function:returns_by_name}}
                    ::fbthrift::Field::new("{{field:name}}", {{#field:type}}{{>lib/ttype}}{{/field:type}}, {{field:key}}),
                    {{/function:returns_by_name}}
                ];
                let _ = p.read_struct_begin(|_| ())?;
                let mut once = false;
                let mut alt = {{!
                    }}{{#function:void?}}{{!
                        }}{{function:upcamel}}StreamExn::Success(()){{!
                    }}{{/function:void?}}{{!
                    }}{{^function:void?}}::std::option::Option::None{{/function:void?}}{{!
                }};
                loop {
                    let (_, fty, fid) = p.read_field_begin(|_| (), RETURNS)?;
                    match ((fty, fid as ::std::primitive::i32), once) {
                        ((::fbthrift::TType::Stop, _), _) => {
                            p.read_field_end()?;
                            break;
                        }
                        (({{#function:return_type}}{{#type:stream_elem_type}}{{>lib/ttype}}{{/type:stream_elem_type}}{{/function:return_type}}, 0i32), false) => {
                            once = true;
                            alt = {{!
                                }}{{^function:void?}}::std::option::Option::Some({{/function:void?}}{{!
                                }}{{function:upcamel}}StreamExn::Success(::fbthrift::Deserialize::read(p)?){{!
                                }}{{^function:void?}}){{/function:void?}}{{!
                            }};
                        }{{!
                        }}{{#function:stream_exceptions}}
                        (({{#field:type}}{{>lib/ttype}}{{/field:type}}, {{field:key}}), false) => {
                            once = true;
                            alt = {{!
                                }}{{^function:void?}}::std::option::Option::Some({{/function:void?}}{{!
                                }}{{function:upcamel}}StreamExn::{{field:rust_name}}(::fbthrift::Deserialize::read(p)?){{!
                                }}{{^function:void?}}){{/function:void?}}{{!
                            }};
                        }{{!
                        }}{{/function:stream_exceptions}}
                        ((ty, _id), false) => p.skip(ty)?,
                        ((badty, badid), true) => return ::std::result::Result::Err(::std::convert::From::from(
                            ::fbthrift::ApplicationException::new(
                                ::fbthrift::ApplicationExceptionErrorCode::ProtocolError,
                                format!(
                                    "unwanted extra union {} field ty {:?} id {}",
                                    "{{function:upcamel}}StreamExn",
                                    badty,
                                    badid,
                                ),
                            )
                        )),
                    }
                    p.read_field_end()?;
                }
                p.read_struct_end()?;{{!
                }}{{#function:void?}}
                ::std::result::Result::Ok(alt){{!
                }}{{/function:void?}}{{!
                }}{{^function:void?}}
                alt.ok_or_else(||
                    ::fbthrift::ApplicationException::new(
                        ::fbthrift::ApplicationExceptionErrorCode::MissingResult,
                        format!("Empty union {}", "{{function:upcamel}}StreamExn"),
                    )
                    .into(),
                ){{!
                }}{{/function:void?}}
            }
        }
        {{#function:stream_has_first_response?}}
        #[derive(Clone, Debug)]
        pub enum {{function:upcamel}}Exn {
            Success({{#function:return_type}}{{#type:stream_first_response_type}}{{>lib/type}}{{/type:stream_first_response_type}}{{/function:return_type}}),{{!
            }}{{#function:exceptions}}
            {{field:rust_name}}({{#field:type}}{{>lib/type}}{{/field:type}}),{{!
            }}{{/function:exceptions}}
            ApplicationException(::fbthrift::ApplicationException),
        }{{!
        }}{{#function:uniqueExceptions}}


        impl ::fbthrift::ExceptionInfo for {{function:upcamel}}Exn {
            fn exn_name(&self) -> &'static str {
                match self {
                    {{function:upcamel}}Exn::Success(_) => panic!("ExceptionInfo::exn_name called on Success"),
                    {{function:upcamel}}Exn::ApplicationException(aexn) => aexn.exn_name(),
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(exn) => exn.exn_name(),
                    {{/function:exceptions}}
                }
            }

            fn exn_value(&self) -> String {
                match self {
                    {{function:upcamel}}Exn::Success(_) => panic!("ExceptionInfo::exn_value called on Success"),
                    {{function:upcamel}}Exn::ApplicationException(aexn) => aexn.exn_value(),
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(exn) => exn.exn_value(),
                    {{/function:exceptions}}
                }
            }

            fn exn_is_declared(&self) -> bool {
                match self {
                    {{function:upcamel}}Exn::Success(_) => panic!("ExceptionInfo::exn_is_declared called on Success"),
                    {{function:upcamel}}Exn::ApplicationException(aexn) => aexn.exn_is_declared(),
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(exn) => exn.exn_is_declared(),
                    {{/function:exceptions}}
                }
            }
        }

        impl ::fbthrift::ResultInfo for {{function:upcamel}}Exn {
            fn result_type(&self) -> ::fbthrift::ResultType {
                match self {
                    {{function:upcamel}}Exn::Success(_) => ::fbthrift::ResultType::Return,
                    {{function:upcamel}}Exn::ApplicationException(_aexn) => ::fbthrift::ResultType::Exception,
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(_exn) => fbthrift::ResultType::Error,
                    {{/function:exceptions}}
                }
            }
        }

        impl ::std::convert::From<{{#field:type}}{{>lib/type}}{{/field:type}}> for {{function:upcamel}}Exn {
            fn from(exn: {{#field:type}}{{>lib/type}}{{/field:type}}) -> Self {
                {{function:upcamel}}Exn::{{field:rust_name}}(exn)
            }
        }{{!
        }}{{/function:uniqueExceptions}}

        impl ::std::convert::From<::fbthrift::ApplicationException> for {{function:upcamel}}Exn {
            fn from(exn: ::fbthrift::ApplicationException) -> Self {
                {{function:upcamel}}Exn::ApplicationException(exn)
            }
        }

        impl ::fbthrift::GetTType for {{function:upcamel}}Exn {
            const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
        }

        impl<P> ::fbthrift::Serialize<P> for {{function:upcamel}}Exn
        where
            P: ::fbthrift::ProtocolWriter,
        {
            fn write(&self, p: &mut P) {
                p.write_struct_begin("{{function:upcamel}}");
                match self {
                    {{function:upcamel}}Exn::Success(inner) => {
                        p.write_field_begin(
                            "Success",
                            {{#function:return_type}}{{#type:stream_first_response_type}}{{>lib/ttype}}{{/type:stream_first_response_type}}{{/function:return_type}},
                            0i16,
                        );
                        inner.write(p);
                        p.write_field_end();
                    }{{!
                    }}{{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(inner) => {
                        p.write_field_begin(
                            "{{field:name}}",
                            {{#field:type}}{{>lib/ttype}}{{/field:type}},
                            {{field:key}},
                        );
                        inner.write(p);
                        p.write_field_end();
                    }{{!
                    }}{{/function:exceptions}}
                    {{function:upcamel}}Exn::ApplicationException(_) => panic!(
                        "Bad union Alt field {} id {}",
                        "ApplicationException",
                        -2147483648i32,
                    ),
                }
                p.write_field_stop();
                p.write_struct_end();
            }
        }

        impl<P> ::fbthrift::Deserialize<P> for {{function:upcamel}}Exn
        where
            P: ::fbthrift::ProtocolReader,
        {
            fn read(p: &mut P) -> ::anyhow::Result<Self> {
                static RETURNS: &[::fbthrift::Field] = &[
                    {{#function:returns_by_name}}
                    ::fbthrift::Field::new("{{field:name}}", {{#field:type}}{{>lib/ttype}}{{/field:type}}, {{field:key}}),
                    {{/function:returns_by_name}}
                ];
                let _ = p.read_struct_begin(|_| ())?;
                let mut once = false;
                let mut alt = {{!
                    }}{{#function:void?}}{{!
                        }}{{function:upcamel}}Exn::Success(()){{!
                    }}{{/function:void?}}{{!
                    }}{{^function:void?}}::std::option::Option::None{{/function:void?}}{{!
                }};
                loop {
                    let (_, fty, fid) = p.read_field_begin(|_| (), RETURNS)?;
                    match ((fty, fid as ::std::primitive::i32), once) {
                        ((::fbthrift::TType::Stop, _), _) => {
                            p.read_field_end()?;
                            break;
                        }
                        (({{#function:return_type}}{{#type:stream_first_response_type}}{{>lib/ttype}}{{/type:stream_first_response_type}}{{/function:return_type}}, 0i32), false) => {
                            once = true;
                            alt = {{!
                                }}{{^function:void?}}::std::option::Option::Some({{/function:void?}}{{!
                                }}{{function:upcamel}}Exn::Success(::fbthrift::Deserialize::read(p)?){{!
                                }}{{^function:void?}}){{/function:void?}}{{!
                            }};
                        }{{!
                        }}{{#function:exceptions}}
                        (({{#field:type}}{{>lib/ttype}}{{/field:type}}, {{field:key}}), false) => {
                            once = true;
                            alt = {{!
                                }}{{^function:void?}}::std::option::Option::Some({{/function:void?}}{{!
                                }}{{function:upcamel}}Exn::{{field:rust_name}}(::fbthrift::Deserialize::read(p)?){{!
                                }}{{^function:void?}}){{/function:void?}}{{!
                            }};
                        }{{!
                        }}{{/function:exceptions}}
                        ((ty, _id), false) => p.skip(ty)?,
                        ((badty, badid), true) => return ::std::result::Result::Err(::std::convert::From::from(
                            ::fbthrift::ApplicationException::new(
                                ::fbthrift::ApplicationExceptionErrorCode::ProtocolError,
                                format!(
                                    "unwanted extra union {} field ty {:?} id {}",
                                    "{{function:upcamel}}Exn",
                                    badty,
                                    badid,
                                ),
                            )
                        )),
                    }
                    p.read_field_end()?;
                }
                p.read_struct_end()?;{{!
                }}{{#function:void?}}
                ::std::result::Result::Ok(alt){{!
                }}{{/function:void?}}{{!
                }}{{^function:void?}}
                alt.ok_or_else(||
                    ::fbthrift::ApplicationException::new(
                        ::fbthrift::ApplicationExceptionErrorCode::MissingResult,
                        format!("Empty union {}", "{{function:upcamel}}Exn"),
                    )
                    .into(),
                ){{!
                }}{{/function:void?}}
            }
        }
        {{/function:stream_has_first_response?}}{{/function:returns_stream?}}{{^function:returns_stream?}}


        #[derive(Clone, Debug)]
        pub enum {{function:upcamel}}Exn {
            Success({{#function:return_type}}{{>lib/type}}{{/function:return_type}}),{{!
            }}{{#function:exceptions}}
            {{field:rust_name}}({{#field:type}}{{>lib/type}}{{/field:type}}),{{!
            }}{{/function:exceptions}}
            ApplicationException(::fbthrift::ApplicationException),
        }{{!
        }}{{#function:uniqueExceptions}}

        impl ::std::convert::From<{{#field:type}}{{>lib/type}}{{/field:type}}> for {{function:upcamel}}Exn {
            fn from(exn: {{#field:type}}{{>lib/type}}{{/field:type}}) -> Self {
                {{function:upcamel}}Exn::{{field:rust_name}}(exn)
            }
        }{{!
        }}{{/function:uniqueExceptions}}

        impl ::std::convert::From<::fbthrift::ApplicationException> for {{function:upcamel}}Exn {
            fn from(exn: ::fbthrift::ApplicationException) -> Self {
                {{function:upcamel}}Exn::ApplicationException(exn)
            }
        }

        impl ::fbthrift::ExceptionInfo for {{function:upcamel}}Exn {
            fn exn_name(&self) -> &'static str {
                match self {
                    {{function:upcamel}}Exn::Success(_) => panic!("ExceptionInfo::exn_name called on Success"),
                    {{function:upcamel}}Exn::ApplicationException(aexn) => aexn.exn_name(),
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(exn) => exn.exn_name(),
                    {{/function:exceptions}}
                }
            }

            fn exn_value(&self) -> String {
                match self {
                    {{function:upcamel}}Exn::Success(_) => panic!("ExceptionInfo::exn_value called on Success"),
                    {{function:upcamel}}Exn::ApplicationException(aexn) => aexn.exn_value(),
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(exn) => exn.exn_value(),
                    {{/function:exceptions}}
                }
            }

            fn exn_is_declared(&self) -> bool {
                match self {
                    {{function:upcamel}}Exn::Success(_) => panic!("ExceptionInfo::exn_is_declared called on Success"),
                    {{function:upcamel}}Exn::ApplicationException(aexn) => aexn.exn_is_declared(),
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(exn) => exn.exn_is_declared(),
                    {{/function:exceptions}}
                }
            }
        }

        impl ::fbthrift::ResultInfo for {{function:upcamel}}Exn {
            fn result_type(&self) -> ::fbthrift::ResultType {
                match self {
                    {{function:upcamel}}Exn::Success(_) => ::fbthrift::ResultType::Return,
                    {{function:upcamel}}Exn::ApplicationException(_aexn) => ::fbthrift::ResultType::Exception,
                    {{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(_exn) => fbthrift::ResultType::Error,
                    {{/function:exceptions}}
                }
            }
        }

        impl ::fbthrift::GetTType for {{function:upcamel}}Exn {
            const TTYPE: ::fbthrift::TType = ::fbthrift::TType::Struct;
        }

        impl<P> ::fbthrift::Serialize<P> for {{function:upcamel}}Exn
        where
            P: ::fbthrift::ProtocolWriter,
        {
            fn write(&self, p: &mut P) {
                if let {{function:upcamel}}Exn::ApplicationException(aexn) = self {
                    return aexn.write(p);
                }
                p.write_struct_begin("{{function:upcamel}}");
                match self {
                    {{function:upcamel}}Exn::Success(inner) => {
                        p.write_field_begin(
                            "Success",
                            {{#function:return_type}}{{>lib/ttype}}{{/function:return_type}},
                            0i16,
                        );
                        inner.write(p);
                        p.write_field_end();
                    }{{!
                    }}{{#function:exceptions}}
                    {{function:upcamel}}Exn::{{field:rust_name}}(inner) => {
                        p.write_field_begin(
                            "{{field:name}}",
                            {{#field:type}}{{>lib/ttype}}{{/field:type}},
                            {{field:key}},
                        );
                        inner.write(p);
                        p.write_field_end();
                    }{{!
                    }}{{/function:exceptions}}
                    {{function:upcamel}}Exn::ApplicationException(_aexn) => unreachable!(),
                }
                p.write_field_stop();
                p.write_struct_end();
            }
        }

        impl<P> ::fbthrift::Deserialize<P> for {{function:upcamel}}Exn
        where
            P: ::fbthrift::ProtocolReader,
        {
            fn read(p: &mut P) -> ::anyhow::Result<Self> {
                static RETURNS: &[::fbthrift::Field] = &[
                    {{#function:returns_by_name}}
                    ::fbthrift::Field::new("{{field:name}}", {{#field:type}}{{>lib/ttype}}{{/field:type}}, {{field:key}}),
                    {{/function:returns_by_name}}
                ];
                let _ = p.read_struct_begin(|_| ())?;
                let mut once = false;
                let mut alt = {{!
                    }}{{#function:void?}}{{!
                        }}{{function:upcamel}}Exn::Success(()){{!
                    }}{{/function:void?}}{{!
                    }}{{^function:void?}}::std::option::Option::None{{/function:void?}}{{!
                }};
                loop {
                    let (_, fty, fid) = p.read_field_begin(|_| (), RETURNS)?;
                    match ((fty, fid as ::std::primitive::i32), once) {
                        ((::fbthrift::TType::Stop, _), _) => {
                            p.read_field_end()?;
                            break;
                        }
                        (({{#function:return_type}}{{>lib/ttype}}{{/function:return_type}}, 0i32), false) => {
                            once = true;
                            alt = {{!
                                }}{{^function:void?}}::std::option::Option::Some({{/function:void?}}{{!
                                }}{{function:upcamel}}Exn::Success(::fbthrift::Deserialize::read(p)?){{!
                                }}{{^function:void?}}){{/function:void?}}{{!
                            }};
                        }{{!
                        }}{{#function:exceptions}}
                        (({{#field:type}}{{>lib/ttype}}{{/field:type}}, {{field:key}}), false) => {
                            once = true;
                            alt = {{!
                                }}{{^function:void?}}::std::option::Option::Some({{/function:void?}}{{!
                                }}{{function:upcamel}}Exn::{{field:rust_name}}(::fbthrift::Deserialize::read(p)?){{!
                                }}{{^function:void?}}){{/function:void?}}{{!
                            }};
                        }{{!
                        }}{{/function:exceptions}}
                        ((ty, _id), false) => p.skip(ty)?,
                        ((badty, badid), true) => return ::std::result::Result::Err(::std::convert::From::from(
                            ::fbthrift::ApplicationException::new(
                                ::fbthrift::ApplicationExceptionErrorCode::ProtocolError,
                                format!(
                                    "unwanted extra union {} field ty {:?} id {}",
                                    "{{function:upcamel}}Exn",
                                    badty,
                                    badid,
                                ),
                            )
                        )),
                    }
                    p.read_field_end()?;
                }
                p.read_struct_end()?;{{!
                }}{{#function:void?}}
                ::std::result::Result::Ok(alt){{!
                }}{{/function:void?}}{{!
                }}{{^function:void?}}
                alt.ok_or_else(||
                    ::fbthrift::ApplicationException::new(
                        ::fbthrift::ApplicationExceptionErrorCode::MissingResult,
                        format!("Empty union {}", "{{function:upcamel}}Exn"),
                    )
                    .into(),
                ){{!
                }}{{/function:void?}}
            }
        }{{!
        }}{{/function:returns_stream?}}{{/function:starts_interaction?}}{{/service:rustFunctions}}
    }
    {{!newline}}
