// @generated by protoc-gen-roto — do not edit
#![allow(unused)]
use roto_runtime::{ProtoAccessor, ProtoBuilder, Result, RotoError, read_varint, RepeatedFieldIterator, RotoMessage};
use core::str;
use bytes::{Bytes, BytesMut, Buf, BufMut};

pub struct UnaryRequest<'a> {
    accessor: roto_runtime::ProtoAccessor<'a>,
    message_offset: Option<usize>,
}

impl<'a> UnaryRequest<'a> {
    pub fn new(data: &'a [u8]) -> roto_runtime::Result<Self> {
        let accessor = roto_runtime::ProtoAccessor::new(data)?;
        let mut message_offset = None;
        for item in accessor.fields() {
            let (offset, tag, _) = item?;
            if tag.field_number == 1 { message_offset = Some(offset); }
        }

        Ok(Self {
            accessor,
message_offset,
        })
    }

    pub fn message(&self) -> roto_runtime::Result<&'a str> {
        let offset = self.message_offset.ok_or(roto_runtime::RotoError::FieldNotFound)?;
        let (bytes, _) = self.accessor.get_value_at(offset)?;
        core::str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)
    }

    pub fn message_or_default(&self) -> roto_runtime::Result<&'a str> {
        self.message().or(Ok(""))
    }

    pub fn has_message(&self) -> bool { self.message_offset.is_some() }

    pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> {
        self.accessor.raw_fields()
    }

}

pub struct UnaryRequestBuilder<'b> {
    builder: roto_runtime::ProtoBuilder<'b>,
    message_written: bool,
}

impl<'b> UnaryRequestBuilder<'b> {
    pub fn builder(buf: &mut [u8]) -> UnaryRequestBuilder<'_> {
        UnaryRequestBuilder {
            builder: roto_runtime::ProtoBuilder::new(buf),
            message_written: false,
        }
    }

    pub fn message(mut self, value: &str) -> roto_runtime::Result<Self> {
        self.builder.write_string(1, value)?;
        self.message_written = true;
        Ok(self)
    }

    pub fn with(mut self, msg: &UnaryRequest<'_>) -> roto_runtime::Result<Self> {
        for item in msg.accessor.raw_fields() {
            let (field_number, raw_bytes) = item?;
            let is_written = match field_number {
                1 => self.message_written,
                _ => false,
            };
            if !is_written {
                self.builder.write_raw(raw_bytes)?;
            }
        }
        Ok(self)
    }

    pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> {
        self.builder.finish()
    }
}

pub struct OwnedUnaryRequest {
    pub data: bytes::Bytes,
}

impl roto_runtime::RotoOwned for OwnedUnaryRequest {
    type Reader<'a> = UnaryRequest<'a>;
    fn reader(&self) -> UnaryRequest<'_> {
        UnaryRequest::new(&self.data).expect("failed to create reader")
    }
}

impl roto_runtime::RotoMessage for OwnedUnaryRequest {
    fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
        Ok(OwnedUnaryRequest { data: buf })
    }

    fn bytes(&self) -> bytes::Bytes {
        self.data.clone()
    }
}

pub struct UnaryResponse<'a> {
    accessor: roto_runtime::ProtoAccessor<'a>,
    reply_offset: Option<usize>,
}

impl<'a> UnaryResponse<'a> {
    pub fn new(data: &'a [u8]) -> roto_runtime::Result<Self> {
        let accessor = roto_runtime::ProtoAccessor::new(data)?;
        let mut reply_offset = None;
        for item in accessor.fields() {
            let (offset, tag, _) = item?;
            if tag.field_number == 1 { reply_offset = Some(offset); }
        }

        Ok(Self {
            accessor,
reply_offset,
        })
    }

    pub fn reply(&self) -> roto_runtime::Result<&'a str> {
        let offset = self.reply_offset.ok_or(roto_runtime::RotoError::FieldNotFound)?;
        let (bytes, _) = self.accessor.get_value_at(offset)?;
        core::str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)
    }

    pub fn reply_or_default(&self) -> roto_runtime::Result<&'a str> {
        self.reply().or(Ok(""))
    }

    pub fn has_reply(&self) -> bool { self.reply_offset.is_some() }

    pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> {
        self.accessor.raw_fields()
    }

}

pub struct UnaryResponseBuilder<'b> {
    builder: roto_runtime::ProtoBuilder<'b>,
    reply_written: bool,
}

impl<'b> UnaryResponseBuilder<'b> {
    pub fn builder(buf: &mut [u8]) -> UnaryResponseBuilder<'_> {
        UnaryResponseBuilder {
            builder: roto_runtime::ProtoBuilder::new(buf),
            reply_written: false,
        }
    }

    pub fn reply(mut self, value: &str) -> roto_runtime::Result<Self> {
        self.builder.write_string(1, value)?;
        self.reply_written = true;
        Ok(self)
    }

    pub fn with(mut self, msg: &UnaryResponse<'_>) -> roto_runtime::Result<Self> {
        for item in msg.accessor.raw_fields() {
            let (field_number, raw_bytes) = item?;
            let is_written = match field_number {
                1 => self.reply_written,
                _ => false,
            };
            if !is_written {
                self.builder.write_raw(raw_bytes)?;
            }
        }
        Ok(self)
    }

    pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> {
        self.builder.finish()
    }
}

pub struct OwnedUnaryResponse {
    pub data: bytes::Bytes,
}

impl roto_runtime::RotoOwned for OwnedUnaryResponse {
    type Reader<'a> = UnaryResponse<'a>;
    fn reader(&self) -> UnaryResponse<'_> {
        UnaryResponse::new(&self.data).expect("failed to create reader")
    }
}

impl roto_runtime::RotoMessage for OwnedUnaryResponse {
    fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
        Ok(OwnedUnaryResponse { data: buf })
    }

    fn bytes(&self) -> bytes::Bytes {
        self.data.clone()
    }
}

pub struct StreamingRequest<'a> {
    accessor: roto_runtime::ProtoAccessor<'a>,
    query_offset: Option<usize>,
}

impl<'a> StreamingRequest<'a> {
    pub fn new(data: &'a [u8]) -> roto_runtime::Result<Self> {
        let accessor = roto_runtime::ProtoAccessor::new(data)?;
        let mut query_offset = None;
        for item in accessor.fields() {
            let (offset, tag, _) = item?;
            if tag.field_number == 1 { query_offset = Some(offset); }
        }

        Ok(Self {
            accessor,
query_offset,
        })
    }

    pub fn query(&self) -> roto_runtime::Result<&'a str> {
        let offset = self.query_offset.ok_or(roto_runtime::RotoError::FieldNotFound)?;
        let (bytes, _) = self.accessor.get_value_at(offset)?;
        core::str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)
    }

    pub fn query_or_default(&self) -> roto_runtime::Result<&'a str> {
        self.query().or(Ok(""))
    }

    pub fn has_query(&self) -> bool { self.query_offset.is_some() }

    pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> {
        self.accessor.raw_fields()
    }

}

pub struct StreamingRequestBuilder<'b> {
    builder: roto_runtime::ProtoBuilder<'b>,
    query_written: bool,
}

impl<'b> StreamingRequestBuilder<'b> {
    pub fn builder(buf: &mut [u8]) -> StreamingRequestBuilder<'_> {
        StreamingRequestBuilder {
            builder: roto_runtime::ProtoBuilder::new(buf),
            query_written: false,
        }
    }

    pub fn query(mut self, value: &str) -> roto_runtime::Result<Self> {
        self.builder.write_string(1, value)?;
        self.query_written = true;
        Ok(self)
    }

    pub fn with(mut self, msg: &StreamingRequest<'_>) -> roto_runtime::Result<Self> {
        for item in msg.accessor.raw_fields() {
            let (field_number, raw_bytes) = item?;
            let is_written = match field_number {
                1 => self.query_written,
                _ => false,
            };
            if !is_written {
                self.builder.write_raw(raw_bytes)?;
            }
        }
        Ok(self)
    }

    pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> {
        self.builder.finish()
    }
}

pub struct OwnedStreamingRequest {
    pub data: bytes::Bytes,
}

impl roto_runtime::RotoOwned for OwnedStreamingRequest {
    type Reader<'a> = StreamingRequest<'a>;
    fn reader(&self) -> StreamingRequest<'_> {
        StreamingRequest::new(&self.data).expect("failed to create reader")
    }
}

impl roto_runtime::RotoMessage for OwnedStreamingRequest {
    fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
        Ok(OwnedStreamingRequest { data: buf })
    }

    fn bytes(&self) -> bytes::Bytes {
        self.data.clone()
    }
}

pub struct StreamingResponse<'a> {
    accessor: roto_runtime::ProtoAccessor<'a>,
    item_offset: Option<usize>,
}

impl<'a> StreamingResponse<'a> {
    pub fn new(data: &'a [u8]) -> roto_runtime::Result<Self> {
        let accessor = roto_runtime::ProtoAccessor::new(data)?;
        let mut item_offset = None;
        for item in accessor.fields() {
            let (offset, tag, _) = item?;
            if tag.field_number == 1 { item_offset = Some(offset); }
        }

        Ok(Self {
            accessor,
item_offset,
        })
    }

    pub fn item(&self) -> roto_runtime::Result<&'a str> {
        let offset = self.item_offset.ok_or(roto_runtime::RotoError::FieldNotFound)?;
        let (bytes, _) = self.accessor.get_value_at(offset)?;
        core::str::from_utf8(bytes).map_err(|_| roto_runtime::RotoError::WireFormatViolation)
    }

    pub fn item_or_default(&self) -> roto_runtime::Result<&'a str> {
        self.item().or(Ok(""))
    }

    pub fn has_item(&self) -> bool { self.item_offset.is_some() }

    pub fn raw_fields(&self) -> roto_runtime::RawFieldIterator<'a> {
        self.accessor.raw_fields()
    }

}

pub struct StreamingResponseBuilder<'b> {
    builder: roto_runtime::ProtoBuilder<'b>,
    item_written: bool,
}

impl<'b> StreamingResponseBuilder<'b> {
    pub fn builder(buf: &mut [u8]) -> StreamingResponseBuilder<'_> {
        StreamingResponseBuilder {
            builder: roto_runtime::ProtoBuilder::new(buf),
            item_written: false,
        }
    }

    pub fn item(mut self, value: &str) -> roto_runtime::Result<Self> {
        self.builder.write_string(1, value)?;
        self.item_written = true;
        Ok(self)
    }

    pub fn with(mut self, msg: &StreamingResponse<'_>) -> roto_runtime::Result<Self> {
        for item in msg.accessor.raw_fields() {
            let (field_number, raw_bytes) = item?;
            let is_written = match field_number {
                1 => self.item_written,
                _ => false,
            };
            if !is_written {
                self.builder.write_raw(raw_bytes)?;
            }
        }
        Ok(self)
    }

    pub fn finish(self) -> roto_runtime::Result<&'b mut [u8]> {
        self.builder.finish()
    }
}

pub struct OwnedStreamingResponse {
    pub data: bytes::Bytes,
}

impl roto_runtime::RotoOwned for OwnedStreamingResponse {
    type Reader<'a> = StreamingResponse<'a>;
    fn reader(&self) -> StreamingResponse<'_> {
        StreamingResponse::new(&self.data).expect("failed to create reader")
    }
}

impl roto_runtime::RotoMessage for OwnedStreamingResponse {
    fn decode(buf: bytes::Bytes) -> roto_runtime::Result<Self> {
        Ok(OwnedStreamingResponse { data: buf })
    }

    fn bytes(&self) -> bytes::Bytes {
        self.data.clone()
    }
}



use tonic::{Request, Response, Status};
use tokio_stream::Stream;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::future::Future;
use tonic::body::BoxBody;
use tower::Service;
use futures_util::StreamExt;
use http_body_util::BodyExt;
use http_body::Body;
use crate::{BufferPool, StatusBody};

#[async_trait::async_trait]
pub trait InteropService: Send + Sync + 'static {
    async fn unary_call(&self, request: Request<OwnedUnaryRequest>) -> std::result::Result<Response<OwnedUnaryResponse>, Status>;
    async fn streaming_call(&self, request: Request<OwnedStreamingRequest>) -> std::result::Result<Response<Pin<Box<dyn Stream<Item = std::result::Result<OwnedStreamingResponse, Status>> + Send>>>, Status>;
}

#[derive(Clone)]
pub struct InteropServiceServer {
    inner: Arc<dyn InteropService>,
    pool: Arc<BufferPool>,
}

impl InteropServiceServer {
    pub fn new(inner: Arc<dyn InteropService>, pool: Arc<BufferPool>) -> Self {
        Self { inner, pool }
    }
}

impl tonic::server::NamedService for InteropServiceServer {
    const NAME: &'static str = "interop.InteropService";
}

impl Service<http::Request<BoxBody>> for InteropServiceServer {
    type Response = http::Response<BoxBody>;
    type Error = std::convert::Infallible;
    type Future = Pin<Box<dyn Future<Output = std::result::Result<Self::Response, Self::Error>> + Send>>;

    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<std::result::Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, req: http::Request<BoxBody>) -> Self::Future {
        let inner = self.inner.clone();
        let pool = self.pool.clone();
        Box::pin(async move {
            let path = req.uri().path().to_string();
            let body = req.into_body();
            let mut buf = pool.get();
            let mut stream = body;
            while let Some(frame_result) = stream.frame().await {
                let frame = frame_result.expect("Body frame error");
                if let Some(data) = frame.data_ref() {
                    buf.put(data.clone());
                }
            }

            let total_len = buf.len();
            let bytes_vec = buf.split_to(total_len).freeze();
            pool.put(buf);
            if bytes_vec.len() < 5 {
                let res_body = BoxBody::new(StatusBody::new(Some(Bytes::from_static(&[0, 0, 0, 0, 0])), 0));
                return Ok(http::Response::builder().status(200).body(res_body).unwrap());
            }

            let payload = bytes_vec.slice(5..);
            let mut routed = false;

            if path == "/interop.InteropService/UnaryCall" {
                let request_msg = match OwnedUnaryRequest::decode(payload) {
                    Ok(msg) => msg,
                    Err(e) => {
                        let res_body = BoxBody::new(StatusBody::new(Some(Bytes::from_static(&[0, 0, 0, 0, 0])), 0));
                        return Ok(http::Response::builder().status(200).body(res_body).unwrap());
                    }
                };

                let response = match inner.unary_call(Request::new(request_msg)).await {
                    Ok(res) => res,
                    Err(e) => {
                        let res_body = BoxBody::new(StatusBody::new(Some(Bytes::from_static(&[0, 0, 0, 0, 0])), 0));
                        return Ok(http::Response::builder().status(200).body(res_body).unwrap());
                    }
                };

                let response_msg = response.into_inner();
                let response_bytes = response_msg.bytes();
                let mut res_buf = pool.get();
                res_buf.put_u8(0);
                let len = response_bytes.len() as u32;
                res_buf.put_slice(&len.to_be_bytes());
                res_buf.put_slice(&response_bytes);
                let frame_len = res_buf.len();
                let frame = res_buf.split_to(frame_len).freeze();
                pool.put(res_buf);
                let res_body = BoxBody::new(StatusBody::new(Some(frame), 0));
                routed = true;
                return Ok(http::Response::builder().status(200).header("content-type", "application/grpc").body(res_body).unwrap());
            }
            if path == "/interop.InteropService/StreamingCall" {
                let res_body = BoxBody::new(StatusBody::new(Some(Bytes::from_static(&[0, 0, 0, 0, 0])), 0));
                return Ok(http::Response::builder().status(200).body(res_body).unwrap());
            }
            if !routed {
                let res_body = BoxBody::new(StatusBody::new(Some(Bytes::from_static(&[0, 0, 0, 0, 0])), 0));
                return Ok(http::Response::builder().status(200).body(res_body).unwrap());
            }
            Ok(http::Response::builder().status(200).body(BoxBody::new(StatusBody::new(None, 0))).unwrap())
        })
    }
}
