<commit_before>use bifrost_hasher::hash_str;
use index::client::IndexComps::Vectorized;
use index::EntryKey;
use ram::cell::Cell;
use ram::schema::{Field, IndexType, Schema};
use ram::types::{Id, Value};
use smallvec::SmallVec;

type FieldName = String;
type Component = [u8; 8];
const UNSETTLED: Component = [0u8; 8];

// Define index rules
// Index can be applied on scala value and scala arrays for both Ranged and Hashed
// Only scala can be use vectorization index
// String for ranged will take first 64-bit, hash will hash the string
// Index on nested fields are allowed

pub struct RangedIndexMeta {
    key: EntryKey,
}

pub struct HashedIndexMeta {
    id: Id,
}

pub struct VectorizedMeta {
    cell_id: Id,
    feature: Component,
    details: Option<VectorizedDetails>,
}

pub struct VectorizedDetails {
    vec_id: Id,
    index: u32,
}

pub enum IndexMeta {
    Ranged(RangedIndexMeta),
    Hashed(HashedIndexMeta),
    Vectorized(VectorizedMeta),
}

pub enum IndexComps {
    Ranged(Component),
    Hashed(Component),
    Vectorized(Component),
}

pub struct IndexRes {
    id: FieldName,
    meta: Vec<IndexMeta>,
}

pub fn make_indices(cell: &Cell, schema: &Schema) {}

pub fn remove_indies(indices: Vec<IndexMeta>) {}

pub fn ensure_indices(cell: &Cell, schema: &Schema, old_indices: Vec<IndexRes>) {}

pub fn probe_cell_indices(cell: &Cell, schema: &Schema) -> Vec<IndexRes> {
    let mut res = vec![];
    probe_field_indices(
        cell.id(),
        &"".to_string(),
        &schema.fields,
        schema.id,
        &cell.data,
        &mut res,
    );
    res
}

fn probe_field_indices(
    id: Id,
    prefix: &FieldName,
    field: &Field,
    schema_id: u32,
    value: &Value,
    metas: &mut Vec<IndexRes>,
) {
    let mut field_name = format!("{} -> {}", prefix, field.name);
    if let &Some(ref fields) = &field.sub_fields {
        for field in fields {
            let value = &value[field.name_id];
            probe_field_indices(id, &field_name, field, schema_id, value, metas);
        }
    } else {
        let mut components = vec![];
        if let &Value::Array(ref array) = value {
            for val in array {
                probe_field_indices(id, &field_name, field, schema_id, value, metas);
            }
        } else if let &Value::PrimArray(ref array) = value {
            for index in &field.indices {
                match index {
                    &IndexType::Ranged => components.append(
                        &mut array
                            .features()
                            .into_iter()
                            .map(|vec| IndexComps::Ranged(vec))
                            .collect(),
                    ),
                    &IndexType::Hashed => components.append(
                        &mut array
                            .hashes()
                            .into_iter()
                            .map(|vec| IndexComps::Hashed(vec))
                            .collect(),
                    ),
                    &IndexType::Vectorized => components.append(
                        &mut array
                            .features()
                            .into_iter()
                            .map(|vec| IndexComps::Vectorized(vec))
                            .collect(),
                    ),
                }
            }
        } else {
            for index in &field.indices {
                match index {
                    &IndexType::Ranged => components.push(IndexComps::Ranged(value.feature())),
                    &IndexType::Hashed => components.push(IndexComps::Hashed(value.hash())),
                    &IndexType::Vectorized => {
                        components.push(IndexComps::Vectorized(value.feature()))
                    }
                }
            }
        }
        let mut metas = vec![];
        for comp in components {
            match comp {
                IndexComps::Hashed(c) => {
                    if c == UNSETTLED {
                        continue;
                    }
                    let id = Id::from_obj(&(schema_id, field_name.clone(), c));
                    metas.push(IndexMeta::Hashed(HashedIndexMeta { id }));
                }
                IndexComps::Ranged(c) => {
                    if c == UNSETTLED {
                        continue;
                    }
                    let mut key = EntryKey::new();
                    let field = hash_str(&field_name);
                    key.extend_from_slice(&id.to_binary()); // Id
                    key.extend_from_slice(&c); // value
                    key.extend_from_slice(&field.to_be_bytes()); // field
                    key.extend_from_slice(&schema_id.to_be_bytes()); // schema id
                    metas.push(IndexMeta::Ranged(RangedIndexMeta { key }));
                }
                IndexComps::Vectorized(c) => {
                    if c == UNSETTLED {
                        continue;
                    }
                    metas.push(IndexMeta::Vectorized(VectorizedMeta {
                        cell_id: id,
                        feature: c,
                        details: None,
                    }));
                },
            }
        }
    }
}
<commit_msg>refactor<commit_after>use bifrost_hasher::hash_str;
use index::client::IndexComps::Vectorized;
use index::EntryKey;
use ram::cell::Cell;
use ram::schema::{Field, IndexType, Schema};
use ram::types::{Id, Value};
use smallvec::SmallVec;

type FieldName = String;
type Component = [u8; 8];
const UNSETTLED: Component = [0u8; 8];

// Define index rules
// Index can be applied on scala value and scala arrays for both Ranged and Hashed
// Only scala can be use vectorization index
// String for ranged will take first 64-bit, hash will hash the string
// Index on nested fields are allowed

pub struct RangedIndexMeta {
    key: EntryKey,
}

pub struct HashedIndexMeta {
    id: Id,
}

pub struct VectorizedMeta {
    cell_id: Id,
    feature: Component,
    details: Option<VectorizedDetails>,
}

pub struct VectorizedDetails {
    vec_id: Id,
    index: u32,
}

pub enum IndexMeta {
    Ranged(RangedIndexMeta),
    Hashed(HashedIndexMeta),
    Vectorized(VectorizedMeta),
}

pub enum IndexComps {
    Ranged(Component),
    Hashed(Component),
    Vectorized(Component),
}

pub struct IndexRes {
    fields: FieldName,
    meta: Vec<IndexMeta>,
}

pub fn make_indices(cell: &Cell, schema: &Schema) {}

pub fn remove_indies(indices: Vec<IndexMeta>) {}

pub fn ensure_indices(cell: &Cell, schema: &Schema, old_indices: Vec<IndexRes>) {}

pub fn probe_cell_indices(cell: &Cell, schema: &Schema) -> Vec<IndexRes> {
    let mut res = vec![];
    probe_field_indices(
        cell.id(),
        &"".to_string(),
        &schema.fields,
        schema.id,
        &cell.data,
        &mut res,
    );
    res
}

fn probe_field_indices(
    id: Id,
    fields: &FieldName,
    field: &Field,
    schema_id: u32,
    value: &Value,
    res: &mut Vec<IndexRes>,
) {
    if let &Some(ref fields) = &field.sub_fields {
        for field in fields {
            let value = &value[field.name_id];
            let fields = format!("{} -> {}", fields, field.name);
            probe_field_indices(
                id,
                &fields,
                field,
                schema_id,
                value,
                res,
            );
        }
    } else {
        let mut components = vec![];
        if let &Value::Array(ref array) = value {
            for val in array {
                probe_field_indices(id, &fields, field, schema_id, value, res);
            }
        } else if let &Value::PrimArray(ref array) = value {
            for index in &field.indices {
                match index {
                    &IndexType::Ranged => components.append(
                        &mut array
                            .features()
                            .into_iter()
                            .map(|vec| IndexComps::Ranged(vec))
                            .collect(),
                    ),
                    &IndexType::Hashed => components.append(
                        &mut array
                            .hashes()
                            .into_iter()
                            .map(|vec| IndexComps::Hashed(vec))
                            .collect(),
                    ),
                    &IndexType::Vectorized => components.append(
                        &mut array
                            .features()
                            .into_iter()
                            .map(|vec| IndexComps::Vectorized(vec))
                            .collect(),
                    ),
                }
            }
        } else {
            for index in &field.indices {
                match index {
                    &IndexType::Ranged => components.push(IndexComps::Ranged(value.feature())),
                    &IndexType::Hashed => components.push(IndexComps::Hashed(value.hash())),
                    &IndexType::Vectorized => {
                        components.push(IndexComps::Vectorized(value.feature()))
                    }
                }
            }
        }
        let mut metas = vec![];
        for comp in components {
            match comp {
                IndexComps::Hashed(c) => {
                    if c == UNSETTLED {
                        continue;
                    }
                    let id = Id::from_obj(&(schema_id, fields.clone(), c));
                    metas.push(IndexMeta::Hashed(HashedIndexMeta { id }));
                }
                IndexComps::Ranged(c) => {
                    if c == UNSETTLED {
                        continue;
                    }
                    let mut key = EntryKey::new();
                    let field = hash_str(&fields);
                    key.extend_from_slice(&id.to_binary()); // Id
                    key.extend_from_slice(&c); // value
                    key.extend_from_slice(&field.to_be_bytes()); // field
                    key.extend_from_slice(&schema_id.to_be_bytes()); // schema id
                    metas.push(IndexMeta::Ranged(RangedIndexMeta { key }));
                }
                IndexComps::Vectorized(c) => {
                    if c == UNSETTLED {
                        continue;
                    }
                    metas.push(IndexMeta::Vectorized(VectorizedMeta {
                        cell_id: id,
                        feature: c,
                        details: None,
                    }));
                }
            }
        }
        res.push(IndexRes {
            fields: fields.clone(),
            meta: metas
        });
    }
}
<|endoftext|>


<commit_before><commit_msg>code moved to mod.rs<commit_after><|endoftext|>


<commit_before>use crate::{
    channels::Channels,
    consumer_status::ConsumerStatus,
    executor::Executor,
    options::{BasicAckOptions, BasicCancelOptions, BasicNackOptions, BasicRejectOptions},
    socket_state::SocketStateHandle,
    types::ShortUInt,
    DeliveryTag, Error, PromiseResolver, Result,
};
use crossbeam_channel::{Receiver, Sender};
use log::trace;
use std::{fmt, future::Future, sync::Arc};

pub(crate) struct InternalRPC {
    rpc: Receiver<InternalCommand>,
    handle: InternalRPCHandle,
}

#[derive(Clone)]
pub(crate) struct InternalRPCHandle {
    sender: Sender<InternalCommand>,
    waker: SocketStateHandle,
    executor: Arc<dyn Executor>,
}

impl InternalRPCHandle {
    pub(crate) fn basic_ack(
        &self,
        channel_id: u16,
        delivery_tag: DeliveryTag,
        options: BasicAckOptions,
        resolver: PromiseResolver<()>,
    ) {
        self.send(InternalCommand::BasicAck(
            channel_id,
            delivery_tag,
            options,
            resolver,
        ));
    }

    pub(crate) fn basic_nack(
        &self,
        channel_id: u16,
        delivery_tag: DeliveryTag,
        options: BasicNackOptions,
        resolver: PromiseResolver<()>,
    ) {
        self.send(InternalCommand::BasicNack(
            channel_id,
            delivery_tag,
            options,
            resolver,
        ));
    }

    pub(crate) fn basic_reject(
        &self,
        channel_id: u16,
        delivery_tag: DeliveryTag,
        options: BasicRejectOptions,
        resolver: PromiseResolver<()>,
    ) {
        self.send(InternalCommand::BasicReject(
            channel_id,
            delivery_tag,
            options,
            resolver,
        ));
    }

    pub(crate) fn cancel_consumer(
        &self,
        channel_id: u16,
        consumer_tag: String,
        consumer_status: ConsumerStatus,
    ) {
        self.send(InternalCommand::CancelConsumer(
            channel_id,
            consumer_tag,
            consumer_status,
        ));
    }

    pub(crate) fn close_channel(&self, channel_id: u16, reply_code: ShortUInt, reply_text: String) {
        self.send(InternalCommand::CloseChannel(
            channel_id, reply_code, reply_text,
        ));
    }

    pub(crate) fn close_connection(
        &self,
        reply_code: ShortUInt,
        reply_text: String,
        class_id: ShortUInt,
        method_id: ShortUInt,
    ) {
        self.set_connection_closing();
        self.send(InternalCommand::CloseConnection(
            reply_code, reply_text, class_id, method_id,
        ));
    }

    pub(crate) fn send_connection_close_ok(&self, error: Error) {
        self.send(InternalCommand::SendConnectionCloseOk(error));
    }

    pub(crate) fn remove_channel(&self, channel_id: u16, error: Error) {
        self.send(InternalCommand::RemoveChannel(channel_id, error));
    }

    pub(crate) fn set_connection_closing(&self) {
        self.send(InternalCommand::SetConnectionClosing);
    }

    pub(crate) fn set_connection_closed(&self, error: Error) {
        self.send(InternalCommand::SetConnectionClosed(error));
    }

    pub(crate) fn set_connection_error(&self, error: Error) {
        self.send(InternalCommand::SetConnectionError(error));
    }

    fn send(&self, command: InternalCommand) {
        trace!("Queuing internal RPC command: {:?}", command);
        // The only scenario where this can fail if this is the IoLoop already exited
        let _ = self.sender.send(command);
        self.waker.wake();
    }

    pub(crate) fn register_internal_future(
        &self,
        f: impl Future<Output = Result<()>> + Send + 'static,
    ) -> Result<()> {
        let internal_rpc = self.clone();
        self.executor.spawn(Box::pin(async move {
            if let Err(err) = f.await {
                internal_rpc.set_connection_error(err);
            }
        }))
    }

    fn register_internal_future_with_resolver(
        &self,
        f: impl Future<Output = Result<()>> + Send + 'static,
        resolver: PromiseResolver<()>,
    ) -> Result<()> {
        self.executor.spawn(Box::pin(async move {
            let res = f.await;
            resolver.swear(res);
        }))
    }
}

impl fmt::Debug for InternalRPCHandle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("InternalRPCHandle").finish()
    }
}

#[derive(Debug)]
enum InternalCommand {
    BasicAck(u16, DeliveryTag, BasicAckOptions, PromiseResolver<()>),
    BasicNack(u16, DeliveryTag, BasicNackOptions, PromiseResolver<()>),
    BasicReject(u16, DeliveryTag, BasicRejectOptions, PromiseResolver<()>),
    CancelConsumer(u16, String, ConsumerStatus),
    CloseChannel(u16, ShortUInt, String),
    CloseConnection(ShortUInt, String, ShortUInt, ShortUInt),
    SendConnectionCloseOk(Error),
    RemoveChannel(u16, Error),
    SetConnectionClosing,
    SetConnectionClosed(Error),
    SetConnectionError(Error),
}

impl InternalRPC {
    pub(crate) fn new(executor: Arc<dyn Executor>, waker: SocketStateHandle) -> Self {
        let (sender, rpc) = crossbeam_channel::unbounded();
        let handle = InternalRPCHandle {
            sender,
            waker,
            executor,
        };
        Self { rpc, handle }
    }

    pub(crate) fn handle(&self) -> InternalRPCHandle {
        self.handle.clone()
    }

    pub(crate) fn poll(&self, channels: &Channels) -> Result<()> {
        while let Ok(command) = self.rpc.try_recv() {
            self.run(command, channels)?;
        }
        Ok(())
    }

    fn run(&self, command: InternalCommand, channels: &Channels) -> Result<()> {
        use InternalCommand::*;

        trace!("Handling internal RPC command: {:?}", command);
        match command {
            BasicAck(channel_id, delivery_tag, options, resolver) => channels
                .get(channel_id)
                .map(|channel| {
                    self.handle.register_internal_future_with_resolver(
                        channel.basic_ack(delivery_tag, options),
                        resolver,
                    )
                })
                .unwrap_or(Ok(())),
            BasicNack(channel_id, delivery_tag, options, resolver) => channels
                .get(channel_id)
                .map(|channel| {
                    self.handle.register_internal_future_with_resolver(
                        channel.basic_nack(delivery_tag, options),
                        resolver,
                    )
                })
                .unwrap_or(Ok(())),
            BasicReject(channel_id, delivery_tag, options, resolver) => channels
                .get(channel_id)
                .map(|channel| {
                    self.handle.register_internal_future_with_resolver(
                        channel.basic_reject(delivery_tag, options),
                        resolver,
                    )
                })
                .unwrap_or(Ok(())),
            CancelConsumer(channel_id, consumer_tag, consumer_status) => channels
                .get(channel_id)
                .map(|channel| {
                    if channel.status().connected() && consumer_status.state().is_active() {
                        self.handle.register_internal_future(
                            channel.basic_cancel(&consumer_tag, BasicCancelOptions::default()),
                        )
                    } else {
                        Ok(())
                    }
                })
                .unwrap_or(Ok(())),
            CloseChannel(channel_id, reply_code, reply_text) => channels
                .get(channel_id)
                .map(|channel| {
                    self.handle
                        .register_internal_future(channel.close(reply_code, &reply_text))
                })
                .unwrap_or(Ok(())),
            CloseConnection(reply_code, reply_text, class_id, method_id) => channels
                .get(0)
                .map(|channel0| {
                    self.handle
                        .register_internal_future(channel0.connection_close(
                            reply_code,
                            &reply_text,
                            class_id,
                            method_id,
                        ))
                })
                .unwrap_or(Ok(())),
            SendConnectionCloseOk(error) => channels
                .get(0)
                .map(|channel| {
                    self.handle
                        .register_internal_future(channel.connection_close_ok(error))
                })
                .unwrap_or(Ok(())),
            RemoveChannel(channel_id, error) => channels.remove(channel_id, error),
            SetConnectionClosing => {
                channels.set_connection_closing();
                Ok(())
            }
            SetConnectionClosed(error) => channels.set_connection_closed(error),
            SetConnectionError(error) => channels.set_connection_error(error),
        }
    }
}
<commit_msg>RPC: Resolve promises when preconditions fail<commit_after>use crate::{
    channels::Channels,
    consumer_status::ConsumerStatus,
    executor::Executor,
    options::{BasicAckOptions, BasicCancelOptions, BasicNackOptions, BasicRejectOptions},
    socket_state::SocketStateHandle,
    types::ShortUInt,
    DeliveryTag, Error, PromiseResolver, Result,
};
use crossbeam_channel::{Receiver, Sender};
use log::trace;
use std::{fmt, future::Future, sync::Arc};

pub(crate) struct InternalRPC {
    rpc: Receiver<InternalCommand>,
    handle: InternalRPCHandle,
}

#[derive(Clone)]
pub(crate) struct InternalRPCHandle {
    sender: Sender<InternalCommand>,
    waker: SocketStateHandle,
    executor: Arc<dyn Executor>,
}

impl InternalRPCHandle {
    pub(crate) fn basic_ack(
        &self,
        channel_id: u16,
        delivery_tag: DeliveryTag,
        options: BasicAckOptions,
        resolver: PromiseResolver<()>,
    ) {
        self.send(InternalCommand::BasicAck(
            channel_id,
            delivery_tag,
            options,
            resolver,
        ));
    }

    pub(crate) fn basic_nack(
        &self,
        channel_id: u16,
        delivery_tag: DeliveryTag,
        options: BasicNackOptions,
        resolver: PromiseResolver<()>,
    ) {
        self.send(InternalCommand::BasicNack(
            channel_id,
            delivery_tag,
            options,
            resolver,
        ));
    }

    pub(crate) fn basic_reject(
        &self,
        channel_id: u16,
        delivery_tag: DeliveryTag,
        options: BasicRejectOptions,
        resolver: PromiseResolver<()>,
    ) {
        self.send(InternalCommand::BasicReject(
            channel_id,
            delivery_tag,
            options,
            resolver,
        ));
    }

    pub(crate) fn cancel_consumer(
        &self,
        channel_id: u16,
        consumer_tag: String,
        consumer_status: ConsumerStatus,
    ) {
        self.send(InternalCommand::CancelConsumer(
            channel_id,
            consumer_tag,
            consumer_status,
        ));
    }

    pub(crate) fn close_channel(&self, channel_id: u16, reply_code: ShortUInt, reply_text: String) {
        self.send(InternalCommand::CloseChannel(
            channel_id, reply_code, reply_text,
        ));
    }

    pub(crate) fn close_connection(
        &self,
        reply_code: ShortUInt,
        reply_text: String,
        class_id: ShortUInt,
        method_id: ShortUInt,
    ) {
        self.set_connection_closing();
        self.send(InternalCommand::CloseConnection(
            reply_code, reply_text, class_id, method_id,
        ));
    }

    pub(crate) fn send_connection_close_ok(&self, error: Error) {
        self.send(InternalCommand::SendConnectionCloseOk(error));
    }

    pub(crate) fn remove_channel(&self, channel_id: u16, error: Error) {
        self.send(InternalCommand::RemoveChannel(channel_id, error));
    }

    pub(crate) fn set_connection_closing(&self) {
        self.send(InternalCommand::SetConnectionClosing);
    }

    pub(crate) fn set_connection_closed(&self, error: Error) {
        self.send(InternalCommand::SetConnectionClosed(error));
    }

    pub(crate) fn set_connection_error(&self, error: Error) {
        self.send(InternalCommand::SetConnectionError(error));
    }

    fn send(&self, command: InternalCommand) {
        trace!("Queuing internal RPC command: {:?}", command);
        // The only scenario where this can fail if this is the IoLoop already exited
        let _ = self.sender.send(command);
        self.waker.wake();
    }

    pub(crate) fn register_internal_future(
        &self,
        f: impl Future<Output = Result<()>> + Send + 'static,
    ) -> Result<()> {
        let internal_rpc = self.clone();
        self.executor.spawn(Box::pin(async move {
            if let Err(err) = f.await {
                internal_rpc.set_connection_error(err);
            }
        }))
    }

    fn register_internal_future_with_resolver(
        &self,
        f: impl Future<Output = Result<()>> + Send + 'static,
        resolver: PromiseResolver<()>,
    ) -> Result<()> {
        self.executor.spawn(Box::pin(async move {
            let res = f.await;
            resolver.swear(res);
        }))
    }
}

impl fmt::Debug for InternalRPCHandle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("InternalRPCHandle").finish()
    }
}

#[derive(Debug)]
enum InternalCommand {
    BasicAck(u16, DeliveryTag, BasicAckOptions, PromiseResolver<()>),
    BasicNack(u16, DeliveryTag, BasicNackOptions, PromiseResolver<()>),
    BasicReject(u16, DeliveryTag, BasicRejectOptions, PromiseResolver<()>),
    CancelConsumer(u16, String, ConsumerStatus),
    CloseChannel(u16, ShortUInt, String),
    CloseConnection(ShortUInt, String, ShortUInt, ShortUInt),
    SendConnectionCloseOk(Error),
    RemoveChannel(u16, Error),
    SetConnectionClosing,
    SetConnectionClosed(Error),
    SetConnectionError(Error),
}

impl InternalRPC {
    pub(crate) fn new(executor: Arc<dyn Executor>, waker: SocketStateHandle) -> Self {
        let (sender, rpc) = crossbeam_channel::unbounded();
        let handle = InternalRPCHandle {
            sender,
            waker,
            executor,
        };
        Self { rpc, handle }
    }

    pub(crate) fn handle(&self) -> InternalRPCHandle {
        self.handle.clone()
    }

    pub(crate) fn poll(&self, channels: &Channels) -> Result<()> {
        while let Ok(command) = self.rpc.try_recv() {
            self.run(command, channels)?;
        }
        Ok(())
    }

    fn run(&self, command: InternalCommand, channels: &Channels) -> Result<()> {
        use InternalCommand::*;

        let get_channel = |id| channels.get(id).ok_or(Error::InvalidChannel(id));

        trace!("Handling internal RPC command: {:?}", command);
        match command {
            BasicAck(channel_id, delivery_tag, options, resolver) => {
                let channel = get_channel(channel_id);
                self.handle.register_internal_future_with_resolver(
                    async move { channel?.basic_ack(delivery_tag, options).await },
                    resolver,
                )
            }
            BasicNack(channel_id, delivery_tag, options, resolver) => {
                let channel = get_channel(channel_id);
                self.handle.register_internal_future_with_resolver(
                    async move { channel?.basic_nack(delivery_tag, options).await },
                    resolver,
                )
            }
            BasicReject(channel_id, delivery_tag, options, resolver) => {
                let channel = get_channel(channel_id);
                self.handle.register_internal_future_with_resolver(
                    async move { channel?.basic_reject(delivery_tag, options).await },
                    resolver,
                )
            }
            CancelConsumer(channel_id, consumer_tag, consumer_status) => {
                let channel = get_channel(channel_id);
                self.handle.register_internal_future(async move {
                    let channel = channel?;
                    if channel.status().connected() && consumer_status.state().is_active() {
                        channel
                            .basic_cancel(&consumer_tag, BasicCancelOptions::default())
                            .await
                    } else {
                        Ok(())
                    }
                })
            }
            CloseChannel(channel_id, reply_code, reply_text) => {
                let channel = get_channel(channel_id);
                self.handle.register_internal_future(async move {
                    channel?.close(reply_code, &reply_text).await
                })
            }
            CloseConnection(reply_code, reply_text, class_id, method_id) => {
                let channel0 = get_channel(0);
                self.handle.register_internal_future(async move {
                    channel0?
                        .connection_close(reply_code, &reply_text, class_id, method_id)
                        .await
                })
            }
            SendConnectionCloseOk(error) => {
                let channel0 = get_channel(0);
                self.handle.register_internal_future(async move {
                    channel0?.connection_close_ok(error).await
                })
            }
            RemoveChannel(channel_id, error) => channels.remove(channel_id, error),
            SetConnectionClosing => {
                channels.set_connection_closing();
                Ok(())
            }
            SetConnectionClosed(error) => channels.set_connection_closed(error),
            SetConnectionError(error) => channels.set_connection_error(error),
        }
    }
}
<|endoftext|>


<commit_before>//! Hardware Abstraction Layer
//!
//! The goal of this module is to abstract the machine/architecture so that
//! the API is the same no matter the underlying hardware.
//!
//! For now only Xen (x86/x86_64) is supported. A goal for the future would
//! be to be compatible with the virtio standard as well and support Xen arm

use io::{Read, Write, Result};

pub mod mmu;

pub use self::hw_imp::*;

/// Generic console wrapper
pub struct Console<'a>(HwConsoleType<'a>);

impl<'a> Read for Console<'a> {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.0.read(buf)
    }
}

impl<'a> Write for Console<'a> {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.0.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> Result<()> {
        self.0.flush()
    }
}

#[cfg(feature = "xen")]
pub mod xen;

#[cfg(feature = "xen")]
mod hw_imp {
    use super::xen;
    use super::Console;

    use cell::GlobalCellMutRef;

    /// Abstracts the actual hardware console type
    pub type HwConsoleType<'a> = GlobalCellMutRef<'a, xen::console::Console>;

    #[inline]
    /// Unprotected access to the hardware console
    ///
    /// This *SHOULD NOT* be used as is.
    ///
    /// Instead use [`io::stdout()`][stdout] or [`io::stdin()`][stdin]
    ///
    /// [stdout]: ../io/fn.stdout.html
    /// [stdin]: ../io/fn.stdin.html
    pub fn console<'a>() -> Console<'a> {
        Console(xen::console::console())
    }

    #[inline]
    /// Disable local interrupt delivery
    pub fn local_irq_disable() {
        xen::disable_upcalls();
    }

    #[inline]
    /// Enable local interrupt delivery
    pub fn local_irq_enable() {
        xen::enable_upcalls();
    }

    #[inline]
    /// Disable local interrupt delivery and return the previous state of
    /// interrupt delivery
    pub fn local_irq_save() -> usize {
        xen::disable_upcalls() as usize
    }

    #[inline]
    /// Restore a local interrupt delivery state
    pub fn local_irq_restore(state: usize) {
        xen::set_upcalls_state(state as u8);
    }

    /// Work with the state of the application
    pub mod app {
        use hal::xen;

        /// Block the application until an interruption arrives
        #[inline]
        pub fn block() {
            xen::sched::block();
        }

        /// Crash the application
        ///
        /// On certain platform this might be equivalent to
        /// [`exit()`][exit]
        ///
        /// [exit]: fn.exit.html
        #[inline]
        pub fn crash() {
            xen::sched::crash();
        }

        /// Exit the application
        ///
        /// This will also power off the system.
        ///
        /// Note that the error code might be ignored on certain platforms
        #[inline]
        pub fn exit(code: isize) {
            xen::sched::poweroff(code as xen::defs::Ulong);
        }
    }

    #[cfg(feature = "net")]
    /// Network device driver abstraction
    pub mod net {
        use hal::xen::net;

        /// Type of the hardware interface.
        pub type HwInterface = net::XenNetDevice;
    }
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[path="x86"]
pub mod arch {
    pub mod mmu;
    pub mod defs;
    pub mod utils;
}
<commit_msg>hal/net: Add generic discover()<commit_after>//! Hardware Abstraction Layer
//!
//! The goal of this module is to abstract the machine/architecture so that
//! the API is the same no matter the underlying hardware.
//!
//! For now only Xen (x86/x86_64) is supported. A goal for the future would
//! be to be compatible with the virtio standard as well and support Xen arm

use io::{Read, Write, Result};

pub mod mmu;

pub use self::hw_imp::*;

/// Generic console wrapper
pub struct Console<'a>(HwConsoleType<'a>);

impl<'a> Read for Console<'a> {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.0.read(buf)
    }
}

impl<'a> Write for Console<'a> {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.0.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> Result<()> {
        self.0.flush()
    }
}

#[cfg(feature = "xen")]
pub mod xen;

#[cfg(feature = "xen")]
mod hw_imp {
    use super::xen;
    use super::Console;

    use cell::GlobalCellMutRef;

    /// Abstracts the actual hardware console type
    pub type HwConsoleType<'a> = GlobalCellMutRef<'a, xen::console::Console>;

    #[inline]
    /// Unprotected access to the hardware console
    ///
    /// This *SHOULD NOT* be used as is.
    ///
    /// Instead use [`io::stdout()`][stdout] or [`io::stdin()`][stdin]
    ///
    /// [stdout]: ../io/fn.stdout.html
    /// [stdin]: ../io/fn.stdin.html
    pub fn console<'a>() -> Console<'a> {
        Console(xen::console::console())
    }

    #[inline]
    /// Disable local interrupt delivery
    pub fn local_irq_disable() {
        xen::disable_upcalls();
    }

    #[inline]
    /// Enable local interrupt delivery
    pub fn local_irq_enable() {
        xen::enable_upcalls();
    }

    #[inline]
    /// Disable local interrupt delivery and return the previous state of
    /// interrupt delivery
    pub fn local_irq_save() -> usize {
        xen::disable_upcalls() as usize
    }

    #[inline]
    /// Restore a local interrupt delivery state
    pub fn local_irq_restore(state: usize) {
        xen::set_upcalls_state(state as u8);
    }

    /// Work with the state of the application
    pub mod app {
        use hal::xen;

        /// Block the application until an interruption arrives
        #[inline]
        pub fn block() {
            xen::sched::block();
        }

        /// Crash the application
        ///
        /// On certain platform this might be equivalent to
        /// [`exit()`][exit]
        ///
        /// [exit]: fn.exit.html
        #[inline]
        pub fn crash() {
            xen::sched::crash();
        }

        /// Exit the application
        ///
        /// This will also power off the system.
        ///
        /// Note that the error code might be ignored on certain platforms
        #[inline]
        pub fn exit(code: isize) {
            xen::sched::poweroff(code as xen::defs::Ulong);
        }
    }

    #[cfg(feature = "net")]
    /// Network device driver abstraction
    pub mod net {
        use vec::Vec;

        use sync::Arc;
        use sync::spin::RwLock;

        use hal::xen::net;

        use net::Interface;

        /// Type of the hardware interface.
        pub type HwInterface = net::XenNetDevice;

        /// Discover hardware configuration and return a list of existing
        /// interfaces
        pub fn discover() -> Vec<Arc<RwLock<Interface>>> {
            net::discover()
        }
    }
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[path="x86"]
pub mod arch {
    pub mod mmu;
    pub mod defs;
    pub mod utils;
}
<|endoftext|>


<commit_before>use anim::{AnimParam, Key, Interpolation, Sampler};
use luminance::Mode;
use luminance_gl::gl33::Tessellation;

/// A unit plane, aligned with the (x,y) plane.
pub fn new_plane() -> Tessellation {
  let vertices = [
    [ 1., -1., 0.],
    [ 1.,  1., 0.],
    [-1., -1., 0.],
    [-1.,  1., 0.]
  ];

  Tessellation::new(Mode::TriangleStrip, &vertices, None)
}

// A unit cube.
//
//     7-----5
//    /|    /|
//   3-+---1 |
//   | 6---+-4
//   |/    |/
//   2-----0
pub fn new_cube() -> Tessellation {
  let vertices = [
    [ 1., -1.,  1.],
    [ 1.,  1.,  1.],
    [-1., -1.,  1.],
    [-1.,  1.,  1.],
    [ 1., -1., -1.],
    [ 1.,  1., -1.],
    [-1., -1., -1.],
    [-1.,  1., -1.],
  ];

  let indices = [
    0, 1, 2, 2, 1, 3, // front face
    4, 5, 6, 6, 5, 7, // back face
    4, 5, 0, 0, 5, 1, // left face
    2, 3, 6, 6, 3, 7, // right face
    1, 5, 3, 3, 5, 7, // top face
    4, 0, 6, 6, 0, 2  // bottom face
  ];//

  Tessellation::new(Mode::Triangle, &vertices, Some(&indices))
}

// Build a curve connected by segments.
pub fn new_curve_2d(gap: f32, interpolation: Interpolation, points: &[(f32, f32)]) -> Tessellation {
  // convert 2D points into cps
  let cps = points.iter().map(|&(t, x)| Key::new(t, x, interpolation)).collect();
  let param = AnimParam::new(cps);

  let mut t = 0.;
  let mut sampler = Sampler::new();
  let mut vertices = Vec::new(); // FIXME: with_capacity ?

  // sample the curve
  while let Some(y) = sampler.sample(t, &param, true) {
    vertices.push([t, y]);
    t += gap;
  }

  Tessellation::new(Mode::LineStrip, &vertices, None)
}
<commit_msg>Removed useless //<commit_after>use anim::{AnimParam, Key, Interpolation, Sampler};
use luminance::Mode;
use luminance_gl::gl33::Tessellation;

/// A unit plane, aligned with the (x,y) plane.
pub fn new_plane() -> Tessellation {
  let vertices = [
    [ 1., -1., 0.],
    [ 1.,  1., 0.],
    [-1., -1., 0.],
    [-1.,  1., 0.]
  ];

  Tessellation::new(Mode::TriangleStrip, &vertices, None)
}

// A unit cube.
//
//     7-----5
//    /|    /|
//   3-+---1 |
//   | 6---+-4
//   |/    |/
//   2-----0
pub fn new_cube() -> Tessellation {
  let vertices = [
    [ 1., -1.,  1.],
    [ 1.,  1.,  1.],
    [-1., -1.,  1.],
    [-1.,  1.,  1.],
    [ 1., -1., -1.],
    [ 1.,  1., -1.],
    [-1., -1., -1.],
    [-1.,  1., -1.],
  ];

  let indices = [
    0, 1, 2, 2, 1, 3, // front face
    4, 5, 6, 6, 5, 7, // back face
    4, 5, 0, 0, 5, 1, // left face
    2, 3, 6, 6, 3, 7, // right face
    1, 5, 3, 3, 5, 7, // top face
    4, 0, 6, 6, 0, 2  // bottom face
  ];

  Tessellation::new(Mode::Triangle, &vertices, Some(&indices))
}

// Build a curve connected by segments.
pub fn new_curve_2d(gap: f32, interpolation: Interpolation, points: &[(f32, f32)]) -> Tessellation {
  // convert 2D points into cps
  let cps = points.iter().map(|&(t, x)| Key::new(t, x, interpolation)).collect();
  let param = AnimParam::new(cps);

  let mut t = 0.;
  let mut sampler = Sampler::new();
  let mut vertices = Vec::new(); // FIXME: with_capacity ?

  // sample the curve
  while let Some(y) = sampler.sample(t, &param, true) {
    vertices.push([t, y]);
    t += gap;
  }

  Tessellation::new(Mode::LineStrip, &vertices, None)
}
<|endoftext|>


<commit_before>use crate::error::ParseMessageError;
use crate::structs;
use std::fmt;
use std::str::FromStr;

#[derive(Debug)]
pub enum Pw {
    Uid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Sp {
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Gr {
    Gid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Ent {
    Set(u32),
    Get(u32),
    End(u32),
}

#[derive(Debug)]
pub enum ClientMessage {
    Key { user: String },
    Pam { user: String },
    CleanUp,
    RateLimit,
    SectorGroups,
    Pw(Pw),
    Sp(Sp),
    Gr(Gr),
}

#[allow(unused)]
#[derive(Debug)]
pub enum DaemonMessage {
    Success,
    Error { message: String },
    Key { keys: String },
    Pam { result: bool },
    RateLimit { limit: usize },
    SectorGroups { sectors: Vec<structs::SectorGroup> },
    Pw { login: String, uid: u64, gid: u64 },
    Sp { login: String },
    Gr { sector: structs::SectorGroup },
}

impl fmt::Display for Ent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Ent::Set(pid) => write!(f, "set|{}", pid),
            Ent::Get(pid) => write!(f, "get|{}", pid),
            Ent::End(pid) => write!(f, "end|{}", pid),
        }
    }
}

impl fmt::Display for Pw {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Pw::Uid(uid) => write!(f, "uid={}", uid),
            Pw::Nam(name) => write!(f, "name={}", name),
            Pw::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Sp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Sp::Nam(name) => write!(f, "name={}", name),
            Sp::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Gr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Gr::Gid(gid) => write!(f, "gid={}", gid),
            Gr::Nam(name) => write!(f, "name={}", name),
            Gr::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for ClientMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ClientMessage::Key { user } => write!(f, "c:key:{}", user),
            ClientMessage::Pam { user } => write!(f, "c:pam:{}", user),
            ClientMessage::CleanUp => write!(f, "c:cleanup"),
            ClientMessage::RateLimit => write!(f, "c:ratelimit"),
            ClientMessage::SectorGroups => write!(f, "c:sectors"),
            ClientMessage::Pw(pw) => write!(f, "c:pw:{}", pw),
            ClientMessage::Sp(sp) => write!(f, "c:sp:{}", sp),
            ClientMessage::Gr(gr) => write!(f, "c:gr:{}", gr),
        }
    }
}

impl fmt::Display for DaemonMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DaemonMessage::Error { message } => write!(f, "d:error:{}", message),
            DaemonMessage::Success => write!(f, "d:success"),
            DaemonMessage::Key { keys } => write!(f, "d:key:{}", keys),
            DaemonMessage::Pam { result } => write!(f, "d:pam:{}", result),
            DaemonMessage::RateLimit { limit } => write!(f, "d:ratelimit:{}", limit),
            DaemonMessage::SectorGroups { sectors } => {
                let ss: Vec<String> = sectors.iter().map(|s| s.to_string()).collect();
                write!(f, "d:sectors:{}", ss.join("\n"))
            }
            DaemonMessage::Pw { login, uid, gid } => write!(f, "d:pw:{}:{}:{}", login, uid, gid),
            DaemonMessage::Sp { login } => write!(f, "d:sp:{}", login),
            DaemonMessage::Gr { sector } => write!(f, "d:gr:{}", sector),
        }
    }
}

impl FromStr for Ent {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("set|") {
            Ok(Ent::Set(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("get|") {
            Ok(Ent::Get(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("end|") {
            Ok(Ent::End(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Pw {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("uid=") {
            Ok(Pw::Uid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Pw::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Pw::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Sp {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("name=") {
            Ok(Sp::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Sp::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Gr {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("gid=") {
            Ok(Gr::Gid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Gr::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Gr::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for ClientMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("c:key:") {
            Ok(ClientMessage::Key { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("c:pam:") {
            Ok(ClientMessage::Pam { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s == "c:cleanup" {
            Ok(ClientMessage::CleanUp)
        } else if s == "c:ratelimit" {
            Ok(ClientMessage::RateLimit)
        } else if s == "c:sectors" {
            Ok(ClientMessage::SectorGroups)
        } else if s.starts_with("c:pw:") {
            Ok(ClientMessage::Pw(s.get(5..).unwrap_or_default().parse::<Pw>()?))
        } else if s.starts_with("c:sp:") {
            Ok(ClientMessage::Sp(s.get(5..).unwrap_or_default().parse::<Sp>()?))
        } else if s.starts_with("c:gr:") {
            Ok(ClientMessage::Gr(s.get(5..).unwrap_or_default().parse::<Gr>()?))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for DaemonMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("d:key:") {
            Ok(DaemonMessage::Key { keys: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("d:pam:") {
            Ok(DaemonMessage::Pam { result: FromStr::from_str(s.get(6..).unwrap_or("false")).unwrap_or(false) })
        } else if s == "d:success" {
            Ok(DaemonMessage::Success)
        } else if s.starts_with("d:ratelimit:") {
            Ok(DaemonMessage::RateLimit { limit: s.get(12..).unwrap_or("0").parse::<usize>().unwrap_or(0) })
        } else if s.starts_with("d:sectors:") {
            let sectors = s.get(10..)
                           .unwrap_or_default()
                           .split('\n')
                           .filter_map(|l| l.parse::<structs::SectorGroup>().ok())
                           .collect();
            Ok(DaemonMessage::SectorGroups { sectors })
        } else if s.starts_with("d:pw:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(":")
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 3 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let login: String = fields[0].clone();
            match (fields[1].parse::<u64>(), fields[2].parse::<u64>()) {
                (Ok(uid), Ok(gid)) => Ok(DaemonMessage::Pw { login, uid, gid }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:sp:") {
            match s.get(5..).unwrap_or_default().parse::<String>() {
                Ok(login) => Ok(DaemonMessage::Sp { login }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:gr:") {
            match s.get(5..).unwrap_or_default().parse::<structs::SectorGroup>() {
                Ok(sector) => Ok(DaemonMessage::Gr { sector }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else {
            Err(ParseMessageError::ParseDaemonMessageError)
        }
    }
}
<commit_msg>Use char instead of str<commit_after>use crate::error::ParseMessageError;
use crate::structs;
use std::fmt;
use std::str::FromStr;

#[derive(Debug)]
pub enum Pw {
    Uid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Sp {
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Gr {
    Gid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Ent {
    Set(u32),
    Get(u32),
    End(u32),
}

#[derive(Debug)]
pub enum ClientMessage {
    Key { user: String },
    Pam { user: String },
    CleanUp,
    RateLimit,
    SectorGroups,
    Pw(Pw),
    Sp(Sp),
    Gr(Gr),
}

#[allow(unused)]
#[derive(Debug)]
pub enum DaemonMessage {
    Success,
    Error { message: String },
    Key { keys: String },
    Pam { result: bool },
    RateLimit { limit: usize },
    SectorGroups { sectors: Vec<structs::SectorGroup> },
    Pw { login: String, uid: u64, gid: u64 },
    Sp { login: String },
    Gr { sector: structs::SectorGroup },
}

impl fmt::Display for Ent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Ent::Set(pid) => write!(f, "set|{}", pid),
            Ent::Get(pid) => write!(f, "get|{}", pid),
            Ent::End(pid) => write!(f, "end|{}", pid),
        }
    }
}

impl fmt::Display for Pw {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Pw::Uid(uid) => write!(f, "uid={}", uid),
            Pw::Nam(name) => write!(f, "name={}", name),
            Pw::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Sp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Sp::Nam(name) => write!(f, "name={}", name),
            Sp::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Gr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Gr::Gid(gid) => write!(f, "gid={}", gid),
            Gr::Nam(name) => write!(f, "name={}", name),
            Gr::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for ClientMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ClientMessage::Key { user } => write!(f, "c:key:{}", user),
            ClientMessage::Pam { user } => write!(f, "c:pam:{}", user),
            ClientMessage::CleanUp => write!(f, "c:cleanup"),
            ClientMessage::RateLimit => write!(f, "c:ratelimit"),
            ClientMessage::SectorGroups => write!(f, "c:sectors"),
            ClientMessage::Pw(pw) => write!(f, "c:pw:{}", pw),
            ClientMessage::Sp(sp) => write!(f, "c:sp:{}", sp),
            ClientMessage::Gr(gr) => write!(f, "c:gr:{}", gr),
        }
    }
}

impl fmt::Display for DaemonMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DaemonMessage::Error { message } => write!(f, "d:error:{}", message),
            DaemonMessage::Success => write!(f, "d:success"),
            DaemonMessage::Key { keys } => write!(f, "d:key:{}", keys),
            DaemonMessage::Pam { result } => write!(f, "d:pam:{}", result),
            DaemonMessage::RateLimit { limit } => write!(f, "d:ratelimit:{}", limit),
            DaemonMessage::SectorGroups { sectors } => {
                let ss: Vec<String> = sectors.iter().map(|s| s.to_string()).collect();
                write!(f, "d:sectors:{}", ss.join("\n"))
            }
            DaemonMessage::Pw { login, uid, gid } => write!(f, "d:pw:{}:{}:{}", login, uid, gid),
            DaemonMessage::Sp { login } => write!(f, "d:sp:{}", login),
            DaemonMessage::Gr { sector } => write!(f, "d:gr:{}", sector),
        }
    }
}

impl FromStr for Ent {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("set|") {
            Ok(Ent::Set(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("get|") {
            Ok(Ent::Get(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("end|") {
            Ok(Ent::End(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Pw {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("uid=") {
            Ok(Pw::Uid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Pw::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Pw::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Sp {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("name=") {
            Ok(Sp::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Sp::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Gr {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("gid=") {
            Ok(Gr::Gid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Gr::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Gr::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for ClientMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("c:key:") {
            Ok(ClientMessage::Key { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("c:pam:") {
            Ok(ClientMessage::Pam { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s == "c:cleanup" {
            Ok(ClientMessage::CleanUp)
        } else if s == "c:ratelimit" {
            Ok(ClientMessage::RateLimit)
        } else if s == "c:sectors" {
            Ok(ClientMessage::SectorGroups)
        } else if s.starts_with("c:pw:") {
            Ok(ClientMessage::Pw(s.get(5..).unwrap_or_default().parse::<Pw>()?))
        } else if s.starts_with("c:sp:") {
            Ok(ClientMessage::Sp(s.get(5..).unwrap_or_default().parse::<Sp>()?))
        } else if s.starts_with("c:gr:") {
            Ok(ClientMessage::Gr(s.get(5..).unwrap_or_default().parse::<Gr>()?))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for DaemonMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("d:key:") {
            Ok(DaemonMessage::Key { keys: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("d:pam:") {
            Ok(DaemonMessage::Pam { result: FromStr::from_str(s.get(6..).unwrap_or("false")).unwrap_or(false) })
        } else if s == "d:success" {
            Ok(DaemonMessage::Success)
        } else if s.starts_with("d:ratelimit:") {
            Ok(DaemonMessage::RateLimit { limit: s.get(12..).unwrap_or("0").parse::<usize>().unwrap_or(0) })
        } else if s.starts_with("d:sectors:") {
            let sectors = s.get(10..)
                           .unwrap_or_default()
                           .split('\n')
                           .filter_map(|l| l.parse::<structs::SectorGroup>().ok())
                           .collect();
            Ok(DaemonMessage::SectorGroups { sectors })
        } else if s.starts_with("d:pw:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 3 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let login: String = fields[0].clone();
            match (fields[1].parse::<u64>(), fields[2].parse::<u64>()) {
                (Ok(uid), Ok(gid)) => Ok(DaemonMessage::Pw { login, uid, gid }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:sp:") {
            match s.get(5..).unwrap_or_default().parse::<String>() {
                Ok(login) => Ok(DaemonMessage::Sp { login }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:gr:") {
            match s.get(5..).unwrap_or_default().parse::<structs::SectorGroup>() {
                Ok(sector) => Ok(DaemonMessage::Gr { sector }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else {
            Err(ParseMessageError::ParseDaemonMessageError)
        }
    }
}
<|endoftext|>


<commit_before>use crate::error::ParseMessageError;
use crate::structs;
use std::fmt;
use std::str::FromStr;

#[derive(Debug)]
pub enum Pw {
    Uid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Sp {
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Gr {
    Gid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Ent {
    Set(u32),
    Get(u32),
    End(u32),
}

#[derive(Debug)]
pub enum ClientMessage {
    Key { user: String },
    Pam { user: String },
    CleanUp,
    RateLimit,
    SectorGroups,
    Pw(Pw),
    Sp(Sp),
    Gr(Gr),
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum DaemonMessage {
    Success,
    Error {
        message: String,
    },
    Key {
        keys: String,
    },
    Pam {
        result: bool,
    },
    RateLimit {
        limit: usize,
        remaining: usize,
        reset: usize,
    },
    SectorGroups {
        sectors: Vec<structs::SectorGroup>,
    },
    Pw {
        login: String,
        uid: u64,
        gid: u64,
        home: String,
        sh: String,
    },
    Sp {
        login: String,
        pass: String,
    },
    Gr {
        sector: structs::SectorGroup,
    },
}

impl fmt::Display for Ent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Ent::Set(pid) => write!(f, "set|{}", pid),
            Ent::Get(pid) => write!(f, "get|{}", pid),
            Ent::End(pid) => write!(f, "end|{}", pid),
        }
    }
}

impl fmt::Display for Pw {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Pw::Uid(uid) => write!(f, "uid={}", uid),
            Pw::Nam(name) => write!(f, "name={}", name),
            Pw::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Sp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Sp::Nam(name) => write!(f, "name={}", name),
            Sp::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Gr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Gr::Gid(gid) => write!(f, "gid={}", gid),
            Gr::Nam(name) => write!(f, "name={}", name),
            Gr::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for ClientMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ClientMessage::Key { user } => write!(f, "c:key:{}", user),
            ClientMessage::Pam { user } => write!(f, "c:pam:{}", user),
            ClientMessage::CleanUp => write!(f, "c:cleanup"),
            ClientMessage::RateLimit => write!(f, "c:ratelimit"),
            ClientMessage::SectorGroups => write!(f, "c:sectors"),
            ClientMessage::Pw(pw) => write!(f, "c:pw:{}", pw),
            ClientMessage::Sp(sp) => write!(f, "c:sp:{}", sp),
            ClientMessage::Gr(gr) => write!(f, "c:gr:{}", gr),
        }
    }
}

impl fmt::Display for DaemonMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DaemonMessage::Error { message } => write!(f, "d:error:{}", message),
            DaemonMessage::Success => write!(f, "d:success"),
            DaemonMessage::Key { keys } => write!(f, "d:key:{}", keys),
            DaemonMessage::Pam { result } => write!(f, "d:pam:{}", result),
            DaemonMessage::RateLimit { limit,
                                       remaining,
                                       reset, } => write!(f, "d:ratelimit:{}:{}:{}", limit, remaining, reset),
            DaemonMessage::SectorGroups { sectors } => {
                let ss: Vec<String> = sectors.iter().map(|s| s.to_string()).collect();
                write!(f, "d:sectors:{}", ss.join("\n"))
            }
            DaemonMessage::Pw { login,
                                uid,
                                gid,
                                home,
                                sh, } => write!(f, "d:pw:{}:{}:{}:{}:{}", login, uid, gid, home, sh),
            DaemonMessage::Sp { login, pass } => write!(f, "d:sp:{}:{}", login, pass),
            DaemonMessage::Gr { sector } => write!(f, "d:gr:{}", sector),
        }
    }
}

impl FromStr for Ent {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("set|") {
            Ok(Ent::Set(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("get|") {
            Ok(Ent::Get(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("end|") {
            Ok(Ent::End(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Pw {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("uid=") {
            Ok(Pw::Uid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Pw::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Pw::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Sp {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("name=") {
            Ok(Sp::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Sp::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Gr {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("gid=") {
            Ok(Gr::Gid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Gr::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Gr::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for ClientMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("c:key:") {
            Ok(ClientMessage::Key { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("c:pam:") {
            Ok(ClientMessage::Pam { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s == "c:cleanup" {
            Ok(ClientMessage::CleanUp)
        } else if s == "c:ratelimit" {
            Ok(ClientMessage::RateLimit)
        } else if s == "c:sectors" {
            Ok(ClientMessage::SectorGroups)
        } else if s.starts_with("c:pw:") {
            Ok(ClientMessage::Pw(s.get(5..).unwrap_or_default().parse::<Pw>()?))
        } else if s.starts_with("c:sp:") {
            Ok(ClientMessage::Sp(s.get(5..).unwrap_or_default().parse::<Sp>()?))
        } else if s.starts_with("c:gr:") {
            Ok(ClientMessage::Gr(s.get(5..).unwrap_or_default().parse::<Gr>()?))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for DaemonMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("d:key:") {
            Ok(DaemonMessage::Key { keys: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("d:pam:") {
            Ok(DaemonMessage::Pam { result: FromStr::from_str(s.get(6..).unwrap_or("false")).unwrap_or(false) })
        } else if s == "d:success" {
            Ok(DaemonMessage::Success)
        } else if s.starts_with("d:ratelimit:") {
            let fields: Vec<String> = s.get(12..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 3 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let limit = fields[0].clone().parse().unwrap_or(0);
            let remaining = fields[1].clone().parse().unwrap_or(0);
            let reset = fields[2].clone().parse().unwrap_or(0);
            Ok(DaemonMessage::RateLimit { limit,
                                          remaining,
                                          reset })
        } else if s.starts_with("d:sectors:") {
            let sectors = s.get(10..)
                           .unwrap_or_default()
                           .split('\n')
                           .filter_map(|l| l.parse::<structs::SectorGroup>().ok())
                           .collect();
            Ok(DaemonMessage::SectorGroups { sectors })
        } else if s.starts_with("d:pw:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 5 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let login: String = fields[0].clone();
            let home: String = fields[3].clone();
            let sh: String = fields[4].clone();
            match (fields[1].parse::<u64>(), fields[2].parse::<u64>()) {
                (Ok(uid), Ok(gid)) => Ok(DaemonMessage::Pw { login,
                                                             uid,
                                                             gid,
                                                             home,
                                                             sh }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:sp:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 2 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            Ok(DaemonMessage::Sp { login: fields[0].clone(),
                                   pass: fields[1].clone() })
        } else if s.starts_with("d:gr:") {
            match s.get(5..).unwrap_or_default().parse::<structs::SectorGroup>() {
                Ok(sector) => Ok(DaemonMessage::Gr { sector }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else {
            Err(ParseMessageError::ParseDaemonMessageError)
        }
    }
}
<commit_msg>Add DividedMessage struct<commit_after>use crate::error::ParseMessageError;
use crate::structs;
use std::fmt;
use std::str::FromStr;

#[derive(Debug)]
pub enum Pw {
    Uid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Sp {
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Gr {
    Gid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Ent {
    Set(u32),
    Get(u32),
    End(u32),
}

pub struct DividedMessage {
    pub cont: bool,
    pub message: String,
}

#[derive(Debug)]
pub enum ClientMessage {
    Key { user: String },
    Pam { user: String },
    CleanUp,
    RateLimit,
    SectorGroups,
    Pw(Pw),
    Sp(Sp),
    Gr(Gr),
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum DaemonMessage {
    Success,
    Error {
        message: String,
    },
    Key {
        keys: String,
    },
    Pam {
        result: bool,
    },
    RateLimit {
        limit: usize,
        remaining: usize,
        reset: usize,
    },
    SectorGroups {
        sectors: Vec<structs::SectorGroup>,
    },
    Pw {
        login: String,
        uid: u64,
        gid: u64,
        home: String,
        sh: String,
    },
    Sp {
        login: String,
        pass: String,
    },
    Gr {
        sector: structs::SectorGroup,
    },
}

impl fmt::Display for Ent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Ent::Set(pid) => write!(f, "set|{}", pid),
            Ent::Get(pid) => write!(f, "get|{}", pid),
            Ent::End(pid) => write!(f, "end|{}", pid),
        }
    }
}

impl fmt::Display for Pw {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Pw::Uid(uid) => write!(f, "uid={}", uid),
            Pw::Nam(name) => write!(f, "name={}", name),
            Pw::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Sp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Sp::Nam(name) => write!(f, "name={}", name),
            Sp::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Gr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Gr::Gid(gid) => write!(f, "gid={}", gid),
            Gr::Nam(name) => write!(f, "name={}", name),
            Gr::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for ClientMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ClientMessage::Key { user } => write!(f, "c:key:{}", user),
            ClientMessage::Pam { user } => write!(f, "c:pam:{}", user),
            ClientMessage::CleanUp => write!(f, "c:cleanup"),
            ClientMessage::RateLimit => write!(f, "c:ratelimit"),
            ClientMessage::SectorGroups => write!(f, "c:sectors"),
            ClientMessage::Pw(pw) => write!(f, "c:pw:{}", pw),
            ClientMessage::Sp(sp) => write!(f, "c:sp:{}", sp),
            ClientMessage::Gr(gr) => write!(f, "c:gr:{}", gr),
        }
    }
}

impl fmt::Display for DaemonMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DaemonMessage::Error { message } => write!(f, "d:error:{}", message),
            DaemonMessage::Success => write!(f, "d:success"),
            DaemonMessage::Key { keys } => write!(f, "d:key:{}", keys),
            DaemonMessage::Pam { result } => write!(f, "d:pam:{}", result),
            DaemonMessage::RateLimit { limit,
                                       remaining,
                                       reset, } => write!(f, "d:ratelimit:{}:{}:{}", limit, remaining, reset),
            DaemonMessage::SectorGroups { sectors } => {
                let ss: Vec<String> = sectors.iter().map(|s| s.to_string()).collect();
                write!(f, "d:sectors:{}", ss.join("\n"))
            }
            DaemonMessage::Pw { login,
                                uid,
                                gid,
                                home,
                                sh, } => write!(f, "d:pw:{}:{}:{}:{}:{}", login, uid, gid, home, sh),
            DaemonMessage::Sp { login, pass } => write!(f, "d:sp:{}:{}", login, pass),
            DaemonMessage::Gr { sector } => write!(f, "d:gr:{}", sector),
        }
    }
}

impl FromStr for Ent {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("set|") {
            Ok(Ent::Set(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("get|") {
            Ok(Ent::Get(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else if s.starts_with("end|") {
            Ok(Ent::End(s.get(4..).unwrap_or_default().parse::<u32>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Pw {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("uid=") {
            Ok(Pw::Uid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Pw::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Pw::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Sp {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("name=") {
            Ok(Sp::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Sp::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Gr {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("gid=") {
            Ok(Gr::Gid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Gr::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Gr::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for ClientMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("c:key:") {
            Ok(ClientMessage::Key { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("c:pam:") {
            Ok(ClientMessage::Pam { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s == "c:cleanup" {
            Ok(ClientMessage::CleanUp)
        } else if s == "c:ratelimit" {
            Ok(ClientMessage::RateLimit)
        } else if s == "c:sectors" {
            Ok(ClientMessage::SectorGroups)
        } else if s.starts_with("c:pw:") {
            Ok(ClientMessage::Pw(s.get(5..).unwrap_or_default().parse::<Pw>()?))
        } else if s.starts_with("c:sp:") {
            Ok(ClientMessage::Sp(s.get(5..).unwrap_or_default().parse::<Sp>()?))
        } else if s.starts_with("c:gr:") {
            Ok(ClientMessage::Gr(s.get(5..).unwrap_or_default().parse::<Gr>()?))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for DaemonMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("d:key:") {
            Ok(DaemonMessage::Key { keys: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("d:pam:") {
            Ok(DaemonMessage::Pam { result: FromStr::from_str(s.get(6..).unwrap_or("false")).unwrap_or(false) })
        } else if s == "d:success" {
            Ok(DaemonMessage::Success)
        } else if s.starts_with("d:ratelimit:") {
            let fields: Vec<String> = s.get(12..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 3 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let limit = fields[0].clone().parse().unwrap_or(0);
            let remaining = fields[1].clone().parse().unwrap_or(0);
            let reset = fields[2].clone().parse().unwrap_or(0);
            Ok(DaemonMessage::RateLimit { limit,
                                          remaining,
                                          reset })
        } else if s.starts_with("d:sectors:") {
            let sectors = s.get(10..)
                           .unwrap_or_default()
                           .split('\n')
                           .filter_map(|l| l.parse::<structs::SectorGroup>().ok())
                           .collect();
            Ok(DaemonMessage::SectorGroups { sectors })
        } else if s.starts_with("d:pw:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 5 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let login: String = fields[0].clone();
            let home: String = fields[3].clone();
            let sh: String = fields[4].clone();
            match (fields[1].parse::<u64>(), fields[2].parse::<u64>()) {
                (Ok(uid), Ok(gid)) => Ok(DaemonMessage::Pw { login,
                                                             uid,
                                                             gid,
                                                             home,
                                                             sh }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:sp:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 2 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            Ok(DaemonMessage::Sp { login: fields[0].clone(),
                                   pass: fields[1].clone() })
        } else if s.starts_with("d:gr:") {
            match s.get(5..).unwrap_or_default().parse::<structs::SectorGroup>() {
                Ok(sector) => Ok(DaemonMessage::Gr { sector }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else {
            Err(ParseMessageError::ParseDaemonMessageError)
        }
    }
}
<|endoftext|>


<commit_before>use yaml_file_handler::yaml_handler::FileHandler as YamlFileHandler;
use bear_lib_terminal::geometry::{Point, Rect};
use bear_lib_terminal::terminal;
use clap::App as Clapp;
use std::cmp::max;
use std::str::FromStr;
use std::net::ToSocketAddrs;
use std::env::home_dir;
use std::path::PathBuf;
use std::time::Duration;
use io;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Options {
	pub name   : String,
	pub server : String,
	pub splash : i32,
	pub time   : Duration,
}

impl Options {
	/// Parses commandline arguments into an [`Options`](#) instance
	///
	/// Optionally reads from a config file in [YAML](http://yaml.org) format, however commandline arguments take preference thereover.
	/// The config file format is trivial: all root keys and values are of the same name and format as long commandline arguments,
	/// see `"example/config.yml"`.
	pub fn parse() -> Options {
		const USAGE: &'static str = "-c --config=[conf]    'Sets config file to load, values will be overriden by commandline args'
		                             -n --name   [name]    'Sets username, will prompt if not specified nor determined'
		                                --splash=[splash]  'Sets the amount of milliseconds the splash will be shown for (0 — off; default/invalid — 1000)'
		                             -t --poll-time [time] 'Sets the amount of time to wait between new message polls, in milliseconds (default/invalid — 3000)'
		                             -s --server [server]  'Sets the server to connect to'";

		let matches = Clapp::new("chattium-oxide-client").version(env!("CARGO_PKG_VERSION"))
		                                                 .author("nabijaczleweli <nabijaczleweli@gmail.com>")
		                                                 .about("Chat client for chattium-oxide-server")
		                                                 .args_from_usage(USAGE)
		                                                 .get_matches();
		let mut name  : Option<String> = None;
		let mut server: Option<String> = None;
		let mut splash: Option<String> = Some("1000".to_string());
		let mut time  : Option<String> = Some("3000".to_string());

		if let Some(conf) = matches.value_of("conf") {
			let mut yaml = YamlFileHandler::new();
			if yaml.add_files(vec![conf]) {
				if let Some(yaml) = yaml.read_all_files().as_ref().map(|all| {
					let mut b = PathBuf::from(conf);
					b.set_extension("");
					&all[b.file_name().unwrap().to_str().unwrap()]
				}) {
					name   = yaml["name"]  .as_str().map(|n| n.to_string());
					server = yaml["server"].as_str().map(|s| s.to_string());
					splash = yaml["splash"].as_str().map(|s| s.to_string());
					time   = yaml["time"]  .as_str().map(|t| t.to_string());
				}
			}
		}

		if let Some(cname)   = matches.value_of("name")   {if cname.len()   > 0 {name   = Some(cname.to_string())}}
		if let Some(cserver) = matches.value_of("server") {if cserver.len() > 0 {server = Some(cserver.to_string())}}
		if let Some(csplash) = matches.value_of("splash") {if csplash.len() > 0 {splash = Some(csplash.to_string())}}
		if let Some(ctime)   = matches.value_of("time")   {if ctime.len() > 0   {time   = Some(ctime.to_string())}}

		if name.is_none() {
			name = Some(match username() {
				Some(uname) =>
					if let Some("") = matches.value_of("name") {
						uname
					} else {
						terminal::print_xy(0, 0, &*&format!("Determined your username to {}.
If that's incorrect, type in your name now. Otherwise, hit <Return>: ", uname));
						terminal::refresh();
						match terminal::read_str(Point::new(0, 2), terminal::state::size().width).into_iter().flat_map(io::maybe_trimmed).next() {
							Some(rname) => rname,
							None        => uname,
						}
					},
				None => {
					let mut tname: Option<String> = None;
					while tname.is_none() {
						terminal::print_xy(0, 0, "No username specified and none could be determined.");
						let second_line = "Please type in your username now: ";
						terminal::print_xy(0, 1, second_line);
						terminal::refresh();
						for rname in terminal::read_str(Point::new(second_line.len() as i32, 1), terminal::state::size().width).into_iter().flat_map(io::maybe_trimmed) {
							tname = Some(rname);
						}
					}
					tname.unwrap()
				},
			});
			terminal::clear(None);
		}

		if server.is_some() {
			server = match validate_address(server.unwrap()) {
				Ok(sserver) => Some(sserver),
				Err(error)  => {
					terminal::print_xy(0, 3, &*&error);
					None
				},
			}
		}
		if server.is_none() {
			terminal::print_xy(0, 0, "No server specified.\nPlease type in the server address now: ");
			terminal::refresh();
			loop {
				if let Some(rserver) = terminal::read_str(Point::new(0, 2), terminal::state::size().width).into_iter().flat_map(io::maybe_trimmed).next() {
					match validate_address(rserver) {
						Ok(rserver) => {
							server = Some(rserver);
							break;
						},
						Err(error) => {
							terminal::clear(Some(Rect::from_size(Point::new(0, 3), terminal::state::size())));
							terminal::print_xy(0, 3, &*&error);
							terminal::refresh();
						},
					}
				}
			}
			terminal::clear(None);
			terminal::refresh();
		}

		assert!(name.is_some());
		assert!(server.is_some());
		assert!(splash.is_some());
		assert!(time.is_some());
		Options{
			name  : name.unwrap(),
			server: server.unwrap(),
			splash: max(i32::from_str(&*&splash.unwrap()).unwrap_or(1000), 0),
			time  : Duration::from_millis(u64::from_str(&*&time.unwrap()).unwrap_or(3000)),
		}
	}
}

/// Extract username from last segment of user's homedir
fn username() -> Option<String> {
	match home_dir() {
		Some(pbuf) =>
			match pbuf.as_path().file_name() {
				Some(fname) => fname.to_str().map(|string| string.to_string()),
				None => None,
			},
		None => None,
	}
}

fn validate_address(address: String) -> Result<String, String> {
	match (&*&address).to_socket_addrs() {
		Ok(_)      => Ok(address),
		Err(error) => Err(format!("{}", error)),
	}
}
<commit_msg>Fix numeric argument parsing from YAML. Adjust option parsing for new clap<commit_after>use yaml_file_handler::yaml_handler::FileHandler as YamlFileHandler;
use bear_lib_terminal::geometry::{Point, Rect};
use bear_lib_terminal::terminal;
use clap::App as Clapp;
use std::cmp::max;
use std::str::FromStr;
use std::net::ToSocketAddrs;
use std::env::home_dir;
use std::path::PathBuf;
use std::time::Duration;
use io;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Options {
	pub name   : String,
	pub server : String,
	pub splash : i32,
	pub time   : Duration,
}

impl Options {
	/// Parses commandline arguments into an [`Options`](#) instance
	///
	/// Optionally reads from a config file in [YAML](http://yaml.org) format, however commandline arguments take preference thereover.
	/// The config file format is trivial: all root keys and values are of the same name and format as long commandline arguments,
	/// see `"example/config.yml"`.
	pub fn parse() -> Options {
		const USAGE: &'static str = "-c --config=[conf]    'Sets config file to load, values will be overriden by commandline args'
		                             -n --name   [name]    'Sets username, will prompt if not specified nor determined'
		                                --splash=[splash]  'Sets the amount of milliseconds the splash will be shown for (0 — off; default/invalid — 1000)'
		                             -t --poll-time [time] 'Sets the amount of time to wait between new message polls, in milliseconds (default/invalid — 3000)'
		                             -s --server [server]  'Sets the server to connect to'";

		let matches = Clapp::new("chattium-oxide-client").version(env!("CARGO_PKG_VERSION"))
		                                                 .author("nabijaczleweli <nabijaczleweli@gmail.com>")
		                                                 .about("Chat client for chattium-oxide-server")
		                                                 .args_from_usage(USAGE)
		                                                 .get_matches();
		let mut name  : Option<String> = None;
		let mut server: Option<String> = None;
		let mut splash: Option<String> = Some("1000".to_string());
		let mut time  : Option<String> = Some("3000".to_string());

		if let Some(config) = matches.value_of("config") {
			let mut yaml = YamlFileHandler::new();
			if yaml.add_files(vec![config]) {
				if let Some(yaml) = yaml.read_all_files().as_ref().map(|all| {
					let mut b = PathBuf::from(config);
					b.set_extension("");
					&all[b.file_name().unwrap().to_str().unwrap()]
				}) {
					name   = yaml["name"]  .as_str().map(|n| n.to_string());
					server = yaml["server"].as_str().map(|s| s.to_string());
					if let Some(spl) = yaml["splash"].as_i64().map(|s| s.to_string()) {
						splash = Some(spl);
					}
					if let Some(tme) = yaml["poll_time"].as_i64().map(|t| t.to_string()) {
						time = Some(tme);
					}
				}
			}
		}

		if let Some(cname)   = matches.value_of("name")      {if cname.len()   > 0 {name   = Some(cname.to_string())}}
		if let Some(cserver) = matches.value_of("server")    {if cserver.len() > 0 {server = Some(cserver.to_string())}}
		if let Some(csplash) = matches.value_of("splash")    {if csplash.len() > 0 {splash = Some(csplash.to_string())}}
		if let Some(ctime)   = matches.value_of("poll-time") {if ctime.len() > 0   {time   = Some(ctime.to_string())}}

		if name.is_none() {
			name = Some(match username() {
				Some(uname) =>
					if let Some("") = matches.value_of("name") {
						uname
					} else {
						terminal::print_xy(0, 0, &*&format!("Determined your username to {}.
If that's incorrect, type in your name now. Otherwise, hit <Return>: ", uname));
						terminal::refresh();
						match terminal::read_str(Point::new(0, 2), terminal::state::size().width).into_iter().flat_map(io::maybe_trimmed).next() {
							Some(rname) => rname,
							None        => uname,
						}
					},
				None => {
					let mut tname: Option<String> = None;
					while tname.is_none() {
						terminal::print_xy(0, 0, "No username specified and none could be determined.");
						let second_line = "Please type in your username now: ";
						terminal::print_xy(0, 1, second_line);
						terminal::refresh();
						for rname in terminal::read_str(Point::new(second_line.len() as i32, 1), terminal::state::size().width).into_iter().flat_map(io::maybe_trimmed) {
							tname = Some(rname);
						}
					}
					tname.unwrap()
				},
			});
			terminal::clear(None);
		}

		if server.is_some() {
			server = match validate_address(server.unwrap()) {
				Ok(sserver) => Some(sserver),
				Err(error)  => {
					terminal::print_xy(0, 3, &*&error);
					None
				},
			}
		}
		if server.is_none() {
			terminal::print_xy(0, 0, "No server specified.\nPlease type in the server address now: ");
			terminal::refresh();
			loop {
				if let Some(rserver) = terminal::read_str(Point::new(0, 2), terminal::state::size().width).into_iter().flat_map(io::maybe_trimmed).next() {
					match validate_address(rserver) {
						Ok(rserver) => {
							server = Some(rserver);
							break;
						},
						Err(error) => {
							terminal::clear(Some(Rect::from_size(Point::new(0, 3), terminal::state::size())));
							terminal::print_xy(0, 3, &*&error);
							terminal::refresh();
						},
					}
				}
			}
			terminal::clear(None);
			terminal::refresh();
		}

		assert!(name.is_some());
		assert!(server.is_some());
		assert!(splash.is_some());
		assert!(time.is_some());
		Options{
			name  : name.unwrap(),
			server: server.unwrap(),
			splash: max(i32::from_str(&*&splash.unwrap()).unwrap_or(1000), 0),
			time  : Duration::from_millis(u64::from_str(&*&time.unwrap()).unwrap_or(3000)),
		}
	}
}

/// Extract username from last segment of user's homedir
fn username() -> Option<String> {
	match home_dir() {
		Some(pbuf) =>
			match pbuf.as_path().file_name() {
				Some(fname) => fname.to_str().map(|string| string.to_string()),
				None => None,
			},
		None => None,
	}
}

fn validate_address(address: String) -> Result<String, String> {
	match (&*&address).to_socket_addrs() {
		Ok(_)      => Ok(address),
		Err(error) => Err(format!("{}", error)),
	}
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

extern crate regex;

use logger;
use env;
use std::process::exit;
use self::regex::Regex;

pub struct Mounter {
    label: Option<String>
}

impl Mounter {

    pub fn new() -> Mounter {
        Mounter{label: None}
    }

    pub fn mount(&self, l: &logger::Logger, e: &env::Env) {
        //self.load_label();
        if !self.verify_label(e.getLabel()) {
            //
            //TODO to log
            //
            exit(0);
        }

        //self.load_fs_type();
        //self.process();
    }

    fn verify_label(&self, templ: &str) -> bool {
        let lbl :String;
        match self.label {
            None    => { return false; },
            Some(ref l) => { lbl = l.to_string(); }
        }

        let res = Regex::new(templ);
        match res {
            Ok(re) => re.is_match(&lbl),
            _      => false
        }
    }
}

#[test]
fn test_verify_label_01() {
    let i = Mounter{label: Some("BNC-124".to_string())};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_02() {
    let i = Mounter{label: Some("XANC-124".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_04() {
    let i = Mounter{label: Some("ANC".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_05() {
    let i = Mounter{label: Some("01234_ ANC".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_06() {
    let i = Mounter{label: Some("01234_ ANC 782883 ".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_07() {
    let i = Mounter{label: Some(" ANC 782883 ".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_08() {
    let i = Mounter{label: Some("ANC---!782883 ".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_09() {
    let i = Mounter{label: Some("01234_ NC 782883 ".to_string())};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}
<commit_msg>add exit to Mounter::mount<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

extern crate regex;

use logger;
use env;
use std::process::exit;
use self::regex::Regex;

//////////////////////////////////////////////////////////////////
pub struct Mounter {
    label: Option<String>
}

impl Mounter {

    pub fn new() -> Mounter {
        Mounter{label: None}
    }

    pub fn mount(&self, l: &logger::Logger, e: &env::Env) {
        //self.load_label();
        if !self.verify_label(e.getLabel()) {
            let i = format!("Label does not match {}.", e.getLabel());
            l.info(&i);
            exit(0);
        }

        //self.load_fs_type();
        //self.process();
    }

    fn verify_label(&self, templ: &str) -> bool {
        let lbl :String;
        match self.label {
            None        => { return false; },
            Some(ref l) => { lbl = l.to_string(); }
        }

        let res = Regex::new(templ);
        match res {
            Ok(re) => re.is_match(&lbl),
            _      => false
        }
    }
}
//////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////
#[test]
fn test_verify_label_01() {
    let i = Mounter{label: Some("BNC-124".to_string())};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_02() {
    let i = Mounter{label: Some("XANC-124".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_04() {
    let i = Mounter{label: Some("ANC".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_05() {
    let i = Mounter{label: Some("01234_ ANC".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_06() {
    let i = Mounter{label: Some("01234_ ANC 782883 ".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_07() {
    let i = Mounter{label: Some(" ANC 782883 ".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_08() {
    let i = Mounter{label: Some("ANC---!782883 ".to_string())};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_09() {
    let i = Mounter{label: Some("01234_ NC 782883 ".to_string())};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}
//////////////////////////////////////////////////////////////////
<|endoftext|>