restructre server network files
This commit is contained in:
		@ -1,106 +1,10 @@
 | 
			
		||||
use crate::model::*;
 | 
			
		||||
use super::*;
 | 
			
		||||
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
// TODO: put conversion and these enums in own file.
 | 
			
		||||
 | 
			
		||||
#[derive(Eq, PartialEq, Clone, Debug)]
 | 
			
		||||
pub enum Package {
 | 
			
		||||
    Json(JsonValue),
 | 
			
		||||
    Command(Command),
 | 
			
		||||
    Binary(Vec<u8>),
 | 
			
		||||
    Error(u16, String),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Eq, PartialEq, Clone, Debug)]
 | 
			
		||||
pub enum JsonValue {
 | 
			
		||||
    Null,
 | 
			
		||||
    True,
 | 
			
		||||
    False,
 | 
			
		||||
    Texture(Texture),
 | 
			
		||||
    TextureArray(Vec<Texture>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
 | 
			
		||||
pub enum Command {
 | 
			
		||||
    #[serde(rename = "ping")]
 | 
			
		||||
    Ping {},
 | 
			
		||||
    #[serde(rename = "pong")]
 | 
			
		||||
    Pong {},
 | 
			
		||||
    #[serde(rename = "query")]
 | 
			
		||||
    Query { query: Vec<String> },
 | 
			
		||||
    #[serde(rename = "get_texture")]
 | 
			
		||||
    GetTexture {
 | 
			
		||||
        id: Option<String>,
 | 
			
		||||
        name: Option<String>,
 | 
			
		||||
    },
 | 
			
		||||
    #[serde(rename = "get_texture_file")]
 | 
			
		||||
    GetTextureData { texture_hash: Sha256 },
 | 
			
		||||
    #[serde(rename = "get_texture_preview")]
 | 
			
		||||
    GetTexturePreview {
 | 
			
		||||
        texture_hash: Sha256,
 | 
			
		||||
        desired_format: TextureFormat,
 | 
			
		||||
    },
 | 
			
		||||
    #[serde(rename = "replace_texture")]
 | 
			
		||||
    ReplaceTexture {
 | 
			
		||||
        old: Option<Texture>,
 | 
			
		||||
        new: Option<Texture>,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
use super::results::*;
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolError> for Package {
 | 
			
		||||
    fn from(item: ProtocolError) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            ProtocolError::BadRequest(msg) => Package::Error(400, msg),
 | 
			
		||||
            ProtocolError::FileNotFound(msg) => Package::Error(404, msg),
 | 
			
		||||
            ProtocolError::Conflict(msg) => Package::Error(409, msg),
 | 
			
		||||
            ProtocolError::InternalServerError(_err) => {
 | 
			
		||||
                Package::Error(500, "Internal Server Error.".to_string())
 | 
			
		||||
            }
 | 
			
		||||
            ProtocolError::NotImplemented => Package::Error(
 | 
			
		||||
                501,
 | 
			
		||||
                "Well, I'm sorry, \
 | 
			
		||||
                 but this feature is still a Todo :/"
 | 
			
		||||
                    .to_string(),
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolResult<Vec<Texture>>> for Package {
 | 
			
		||||
    fn from(item: ProtocolResult<Vec<Texture>>) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            Ok(textures) => Package::Json(JsonValue::TextureArray(textures)),
 | 
			
		||||
            Err(err) => Package::from(err),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolResult<Option<Texture>>> for Package {
 | 
			
		||||
    fn from(item: ProtocolResult<Option<Texture>>) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            Ok(Some(texture)) => Package::Json(JsonValue::Texture(texture)),
 | 
			
		||||
            Ok(None) => Package::Json(JsonValue::Null),
 | 
			
		||||
            Err(err) => Package::from(err),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolResult<Vec<u8>>> for Package {
 | 
			
		||||
    fn from(item: ProtocolResult<Vec<u8>>) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            Ok(bin) => Package::Binary(bin),
 | 
			
		||||
            Err(err) => Package::from(err),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
use crate::protocol::results::ProtocolResult;
 | 
			
		||||
use std::io::*;
 | 
			
		||||
use std::net::*;
 | 
			
		||||
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
pub struct Connection<R: Read + Sized, W: Write + Sized> {
 | 
			
		||||
    reader: R,
 | 
			
		||||
    writer: W,
 | 
			
		||||
@ -0,0 +1,137 @@
 | 
			
		||||
use std::io::*;
 | 
			
		||||
use std::net::*;
 | 
			
		||||
 | 
			
		||||
use std::thread;
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
 | 
			
		||||
use super::*;
 | 
			
		||||
 | 
			
		||||
pub fn listen_forever<H>(handler: H, config: &ProtocolConfig) -> io::Result<()>
 | 
			
		||||
    where
 | 
			
		||||
        H: 'static + ProtocolHandler + Sized,
 | 
			
		||||
{
 | 
			
		||||
    let listener = TcpListener::bind((config.listen_addr.as_str(), config.port))?;
 | 
			
		||||
 | 
			
		||||
    for mut connection in listener.incoming() {
 | 
			
		||||
        // If there is an successful connection,
 | 
			
		||||
        // set timeouts.
 | 
			
		||||
        // We ignore errors here, so they will be caught in the clients thread.
 | 
			
		||||
        let _ = connection.as_mut().map(|stream| {
 | 
			
		||||
            stream.set_read_timeout(Duration::from_secs(config.read_timeout_s).into())?;
 | 
			
		||||
            stream.set_write_timeout(Duration::from_secs(config.read_timeout_s).into())
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let handler = handler.clone();
 | 
			
		||||
        let _ = thread::spawn(move || client_loop(connection?, handler));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn client_loop<H>(connection: TcpStream, mut handler: H) -> io::Result<()>
 | 
			
		||||
    where
 | 
			
		||||
        H: 'static + ProtocolHandler + Sized,
 | 
			
		||||
{
 | 
			
		||||
    let mut connection = Connection::from_tcp(connection)?;
 | 
			
		||||
    'outer: loop {
 | 
			
		||||
        let package = connection.receive()?;
 | 
			
		||||
 | 
			
		||||
        match package {
 | 
			
		||||
            Package::Error(_, _) => {
 | 
			
		||||
                // Just close the connection.
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Json(_) | Package::Binary(_) => {
 | 
			
		||||
                connection.send(&Package::Error(400, "Expected Command.".to_string()))?;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::Ping {}) => {
 | 
			
		||||
                connection.send(&Package::Command(Command::Pong {}))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::Pong {}) => {
 | 
			
		||||
                // Ignore
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::Query { query }) => {
 | 
			
		||||
                connection.send(&Package::from(handler.query(&query[..])))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::GetTexture { id, name }) => match (id, name) {
 | 
			
		||||
                (Some(id), None) => {
 | 
			
		||||
                    connection.send(&Package::from(handler.get_texture_by_id(&id)))?;
 | 
			
		||||
                }
 | 
			
		||||
                (None, Some(name)) => {
 | 
			
		||||
                    connection.send(&Package::from(handler.get_texture_by_name(&name)))?;
 | 
			
		||||
                }
 | 
			
		||||
                _ => {
 | 
			
		||||
                    connection.send(&Package::from(ProtocolError::BadRequest(
 | 
			
		||||
                        "Either 'id' or 'name' must be set!".to_string(),
 | 
			
		||||
                    )))?;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::GetTextureData { texture_hash }) => {
 | 
			
		||||
                connection.send(&Package::from(handler.get_texture_file(texture_hash)))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::GetTexturePreview {
 | 
			
		||||
                                 texture_hash,
 | 
			
		||||
                                 desired_format,
 | 
			
		||||
                             }) => {
 | 
			
		||||
                connection.send(&Package::from(
 | 
			
		||||
                    handler.get_texture_preview(texture_hash, desired_format),
 | 
			
		||||
                ))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // TODO: use less nesting.
 | 
			
		||||
            Package::Command(Command::ReplaceTexture { old, new }) => {
 | 
			
		||||
                match handler.replace_texture(old.clone(), new.clone(), None) {
 | 
			
		||||
                    Ok(ReplaceTextureStatus::Ok) => {
 | 
			
		||||
                        connection.send(&Package::Json(JsonValue::True))?;
 | 
			
		||||
                    }
 | 
			
		||||
                    Ok(ReplaceTextureStatus::NeedTextureData(hash)) => {
 | 
			
		||||
                        connection.send(&Package::Command(Command::GetTextureData {
 | 
			
		||||
                            texture_hash: hash,
 | 
			
		||||
                        }))?;
 | 
			
		||||
 | 
			
		||||
                        let pkg = connection.receive()?;
 | 
			
		||||
                        match pkg {
 | 
			
		||||
                            Package::Binary(data) => {
 | 
			
		||||
                                match handler.replace_texture(old.clone(), new.clone(), Some(data))
 | 
			
		||||
                                    {
 | 
			
		||||
                                        Ok(ReplaceTextureStatus::Ok) => {
 | 
			
		||||
                                            connection.send(&Package::Json(JsonValue::True))?;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        Ok(ReplaceTextureStatus::NeedTextureData(hash)) => {
 | 
			
		||||
                                            panic!("Contract Violation: handler must not return NeedTextureData \
 | 
			
		||||
                                        when data is given.");
 | 
			
		||||
                                        }
 | 
			
		||||
                                        Err(err) => {
 | 
			
		||||
                                            connection.send(&Package::from(err))?;
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                            }
 | 
			
		||||
                            Package::Error(_, _) => {
 | 
			
		||||
                                // Just close the connection.
 | 
			
		||||
                                break 'outer;
 | 
			
		||||
                            }
 | 
			
		||||
                            _ => {
 | 
			
		||||
                                connection.send(&Package::from(ProtocolError::BadRequest(
 | 
			
		||||
                                    "Expected Texture Data!".to_string(),
 | 
			
		||||
                                )))?;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    Err(err) => {
 | 
			
		||||
                        connection.send(&Package::from(err))?;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
@ -1,144 +1,10 @@
 | 
			
		||||
use super::*;
 | 
			
		||||
 | 
			
		||||
use std::io::*;
 | 
			
		||||
use std::net::*;
 | 
			
		||||
mod connection;
 | 
			
		||||
use self::connection::*;
 | 
			
		||||
 | 
			
		||||
use std::thread;
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
mod listen_forever;
 | 
			
		||||
pub use self::listen_forever::*;
 | 
			
		||||
 | 
			
		||||
use crate::model::*;
 | 
			
		||||
 | 
			
		||||
mod protocol_connection;
 | 
			
		||||
use self::protocol_connection::*;
 | 
			
		||||
 | 
			
		||||
use super::results::*;
 | 
			
		||||
 | 
			
		||||
pub fn listen_forever<H>(handler: H, config: &ProtocolConfig) -> io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    H: 'static + ProtocolHandler + Sized,
 | 
			
		||||
{
 | 
			
		||||
    let listener = TcpListener::bind((config.listen_addr.as_str(), config.port))?;
 | 
			
		||||
 | 
			
		||||
    for mut connection in listener.incoming() {
 | 
			
		||||
        // If there is an successful connection,
 | 
			
		||||
        // set timeouts.
 | 
			
		||||
        // We ignore errors here, so they will be caught in the clients thread.
 | 
			
		||||
        let _ = connection.as_mut().map(|stream| {
 | 
			
		||||
            stream.set_read_timeout(Duration::from_secs(config.read_timeout_s).into())?;
 | 
			
		||||
            stream.set_write_timeout(Duration::from_secs(config.read_timeout_s).into())
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let handler = handler.clone();
 | 
			
		||||
        let _ = thread::spawn(move || client_loop(connection?, handler));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn client_loop<H>(connection: TcpStream, mut handler: H) -> io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    H: 'static + ProtocolHandler + Sized,
 | 
			
		||||
{
 | 
			
		||||
    let mut connection = Connection::from_tcp(connection)?;
 | 
			
		||||
    'outer: loop {
 | 
			
		||||
        let package = connection.receive()?;
 | 
			
		||||
 | 
			
		||||
        match package {
 | 
			
		||||
            Package::Error(_, _) => {
 | 
			
		||||
                // Just close the connection.
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Json(_) | Package::Binary(_) => {
 | 
			
		||||
                connection.send(&Package::Error(400, "Expected Command.".to_string()))?;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::Ping {}) => {
 | 
			
		||||
                connection.send(&Package::Command(Command::Pong {}))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::Pong {}) => {
 | 
			
		||||
                // Ignore
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::Query { query }) => {
 | 
			
		||||
                connection.send(&Package::from(handler.query(&query[..])))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::GetTexture { id, name }) => match (id, name) {
 | 
			
		||||
                (Some(id), None) => {
 | 
			
		||||
                    connection.send(&Package::from(handler.get_texture_by_id(&id)))?;
 | 
			
		||||
                }
 | 
			
		||||
                (None, Some(name)) => {
 | 
			
		||||
                    connection.send(&Package::from(handler.get_texture_by_name(&name)))?;
 | 
			
		||||
                }
 | 
			
		||||
                _ => {
 | 
			
		||||
                    connection.send(&Package::from(ProtocolError::BadRequest(
 | 
			
		||||
                        "Either 'id' or 'name' must be set!".to_string(),
 | 
			
		||||
                    )))?;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::GetTextureData { texture_hash }) => {
 | 
			
		||||
                connection.send(&Package::from(handler.get_texture_file(texture_hash)))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Package::Command(Command::GetTexturePreview {
 | 
			
		||||
                texture_hash,
 | 
			
		||||
                desired_format,
 | 
			
		||||
            }) => {
 | 
			
		||||
                connection.send(&Package::from(
 | 
			
		||||
                    handler.get_texture_preview(texture_hash, desired_format),
 | 
			
		||||
                ))?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // TODO: use less nesting.
 | 
			
		||||
            Package::Command(Command::ReplaceTexture { old, new }) => {
 | 
			
		||||
                match handler.replace_texture(old.clone(), new.clone(), None) {
 | 
			
		||||
                    Ok(ReplaceTextureStatus::Ok) => {
 | 
			
		||||
                        connection.send(&Package::Json(JsonValue::True))?;
 | 
			
		||||
                    }
 | 
			
		||||
                    Ok(ReplaceTextureStatus::NeedTextureData(hash)) => {
 | 
			
		||||
                        connection.send(&Package::Command(Command::GetTextureData {
 | 
			
		||||
                            texture_hash: hash,
 | 
			
		||||
                        }))?;
 | 
			
		||||
 | 
			
		||||
                        let pkg = connection.receive()?;
 | 
			
		||||
                        match pkg {
 | 
			
		||||
                            Package::Binary(data) => {
 | 
			
		||||
                                match handler.replace_texture(old.clone(), new.clone(), Some(data))
 | 
			
		||||
                                {
 | 
			
		||||
                                    Ok(ReplaceTextureStatus::Ok) => {
 | 
			
		||||
                                        connection.send(&Package::Json(JsonValue::True))?;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    Ok(ReplaceTextureStatus::NeedTextureData(hash)) => {
 | 
			
		||||
                                        panic!("Contract Violation: handler must not return NeedTextureData \
 | 
			
		||||
                                        when data is given.");
 | 
			
		||||
                                    }
 | 
			
		||||
                                    Err(err) => {
 | 
			
		||||
                                        connection.send(&Package::from(err))?;
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            Package::Error(_, _) => {
 | 
			
		||||
                                // Just close the connection.
 | 
			
		||||
                                break 'outer;
 | 
			
		||||
                            }
 | 
			
		||||
                            _ => {
 | 
			
		||||
                                connection.send(&Package::from(ProtocolError::BadRequest(
 | 
			
		||||
                                    "Expected Texture Data!".to_string(),
 | 
			
		||||
                                )))?;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    Err(err) => {
 | 
			
		||||
                        connection.send(&Package::from(err))?;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
mod package;
 | 
			
		||||
use self::package::*;
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,96 @@
 | 
			
		||||
use crate::model::*;
 | 
			
		||||
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
#[derive(Eq, PartialEq, Clone, Debug)]
 | 
			
		||||
pub enum Package {
 | 
			
		||||
    Json(JsonValue),
 | 
			
		||||
    Command(Command),
 | 
			
		||||
    Binary(Vec<u8>),
 | 
			
		||||
    Error(u16, String),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Eq, PartialEq, Clone, Debug)]
 | 
			
		||||
pub enum JsonValue {
 | 
			
		||||
    Null,
 | 
			
		||||
    True,
 | 
			
		||||
    False,
 | 
			
		||||
    Texture(Texture),
 | 
			
		||||
    TextureArray(Vec<Texture>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
 | 
			
		||||
pub enum Command {
 | 
			
		||||
    #[serde(rename = "ping")]
 | 
			
		||||
    Ping {},
 | 
			
		||||
    #[serde(rename = "pong")]
 | 
			
		||||
    Pong {},
 | 
			
		||||
    #[serde(rename = "query")]
 | 
			
		||||
    Query { query: Vec<String> },
 | 
			
		||||
    #[serde(rename = "get_texture")]
 | 
			
		||||
    GetTexture {
 | 
			
		||||
        id: Option<String>,
 | 
			
		||||
        name: Option<String>,
 | 
			
		||||
    },
 | 
			
		||||
    #[serde(rename = "get_texture_file")]
 | 
			
		||||
    GetTextureData { texture_hash: Sha256 },
 | 
			
		||||
    #[serde(rename = "get_texture_preview")]
 | 
			
		||||
    GetTexturePreview {
 | 
			
		||||
        texture_hash: Sha256,
 | 
			
		||||
        desired_format: TextureFormat,
 | 
			
		||||
    },
 | 
			
		||||
    #[serde(rename = "replace_texture")]
 | 
			
		||||
    ReplaceTexture {
 | 
			
		||||
        old: Option<Texture>,
 | 
			
		||||
        new: Option<Texture>,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
use super::error::*;
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolError> for Package {
 | 
			
		||||
    fn from(item: ProtocolError) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            ProtocolError::BadRequest(msg) => Package::Error(400, msg),
 | 
			
		||||
            ProtocolError::FileNotFound(msg) => Package::Error(404, msg),
 | 
			
		||||
            ProtocolError::Conflict(msg) => Package::Error(409, msg),
 | 
			
		||||
            ProtocolError::InternalServerError(_err) => {
 | 
			
		||||
                Package::Error(500, "Internal Server Error.".to_string())
 | 
			
		||||
            }
 | 
			
		||||
            ProtocolError::NotImplemented => Package::Error(
 | 
			
		||||
                501,
 | 
			
		||||
                "Well, I'm sorry, \
 | 
			
		||||
                 but this feature is still a Todo :/"
 | 
			
		||||
                    .to_string(),
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolResult<Vec<Texture>>> for Package {
 | 
			
		||||
    fn from(item: ProtocolResult<Vec<Texture>>) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            Ok(textures) => Package::Json(JsonValue::TextureArray(textures)),
 | 
			
		||||
            Err(err) => Package::from(err),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolResult<Option<Texture>>> for Package {
 | 
			
		||||
    fn from(item: ProtocolResult<Option<Texture>>) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            Ok(Some(texture)) => Package::Json(JsonValue::Texture(texture)),
 | 
			
		||||
            Ok(None) => Package::Json(JsonValue::Null),
 | 
			
		||||
            Err(err) => Package::from(err),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ProtocolResult<Vec<u8>>> for Package {
 | 
			
		||||
    fn from(item: ProtocolResult<Vec<u8>>) -> Self {
 | 
			
		||||
        match item {
 | 
			
		||||
            Ok(bin) => Package::Binary(bin),
 | 
			
		||||
            Err(err) => Package::from(err),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,13 +1,8 @@
 | 
			
		||||
// TODO: remove on implementation
 | 
			
		||||
#![allow(unused_imports)]
 | 
			
		||||
#![allow(unused_variables)]
 | 
			
		||||
#![allow(dead_code)]
 | 
			
		||||
 | 
			
		||||
mod results;
 | 
			
		||||
pub use self::results::*;
 | 
			
		||||
mod error;
 | 
			
		||||
pub use self::error::*;
 | 
			
		||||
 | 
			
		||||
mod implementation;
 | 
			
		||||
pub use self::implementation::listen_forever;
 | 
			
		||||
pub use self::implementation::*;
 | 
			
		||||
 | 
			
		||||
use crate::model::*;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user