#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![feature(associated_consts, try_from)]
extern crate futures;
extern crate hyper;
#[cfg(test)] extern crate ruma_identifiers;
#[cfg(test)] extern crate serde;
#[cfg(test)] #[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate serde_urlencoded;
use std::convert::TryInto;
use std::io;
use futures::future::FutureFrom;
use hyper::{Method, Request, Response, StatusCode};
use hyper::error::UriError;
pub trait Endpoint {
type Request: TryInto<Request, Error = Error>;
type Response: FutureFrom<Response, Error = Error>;
const METADATA: Metadata;
}
#[derive(Debug)]
pub enum Error {
Hyper(hyper::Error),
Io(io::Error),
SerdeJson(serde_json::Error),
SerdeUrlEncoded(serde_urlencoded::ser::Error),
StatusCode(StatusCode),
Uri(UriError),
}
impl From<hyper::Error> for Error {
fn from(error: hyper::Error) -> Self {
Error::Hyper(error)
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error::Io(error)
}
}
impl From<serde_json::Error> for Error {
fn from(error: serde_json::Error) -> Self {
Error::SerdeJson(error)
}
}
impl From<serde_urlencoded::ser::Error> for Error {
fn from(error: serde_urlencoded::ser::Error) -> Self {
Error::SerdeUrlEncoded(error)
}
}
impl From<UriError> for Error {
fn from(error: UriError) -> Self {
Error::Uri(error)
}
}
#[derive(Clone, Debug)]
pub struct Metadata {
pub description: &'static str,
pub method: Method,
pub name: &'static str,
pub path: &'static str,
pub rate_limited: bool,
pub requires_authentication: bool,
}
#[cfg(test)]
mod tests {
pub mod create {
use std::convert::TryFrom;
use futures::future::{FutureFrom, FutureResult, err, ok};
use hyper::{Method, Request as HyperRequest, Response as HyperResponse, StatusCode};
use ruma_identifiers::{RoomAliasId, RoomId};
use serde_json;
use super::super::{Endpoint as ApiEndpoint, Error, Metadata};
#[derive(Debug)]
pub struct Endpoint;
impl ApiEndpoint for Endpoint {
type Request = Request;
type Response = Response;
const METADATA: Metadata = Metadata {
description: "Add an alias to a room.",
method: Method::Put,
name: "create_alias",
path: "/_matrix/client/r0/directory/room/:room_alias",
rate_limited: false,
requires_authentication: true,
};
}
#[derive(Debug)]
pub struct Request {
pub room_id: RoomId, pub room_alias: RoomAliasId, }
#[derive(Debug, Serialize)]
struct RequestBody {
room_id: RoomId,
}
impl TryFrom<Request> for HyperRequest {
type Error = Error;
fn try_from(request: Request) -> Result<HyperRequest, Self::Error> {
let metadata = Endpoint::METADATA;
let path = metadata.path
.to_string()
.replace(":room_alias", &request.room_alias.to_string());
let mut hyper_request = HyperRequest::new(
metadata.method,
path.parse().map_err(Error::from)?,
);
let request_body = RequestBody {
room_id: request.room_id,
};
hyper_request.set_body(serde_json::to_vec(&request_body).map_err(Error::from)?);
Ok(hyper_request)
}
}
pub struct Response;
impl FutureFrom<HyperResponse> for Response {
type Future = FutureResult<Self, Self::Error>;
type Error = Error;
fn future_from(hyper_response: HyperResponse) -> FutureResult<Self, Self::Error> {
if hyper_response.status() == StatusCode::Ok {
ok(Response)
} else {
err(Error::StatusCode(hyper_response.status().clone()))
}
}
}
}
}