Skip to content

Commit

Permalink
Merge pull request #37 from traP-jp/feat/world-service
Browse files Browse the repository at this point in the history
✨ `WorldService`の実装
  • Loading branch information
H1rono authored Jan 22, 2025
2 parents 384b345 + 20256f5 commit 383fde8
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 1 deletion.
22 changes: 21 additions & 1 deletion server/src/world.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
//! `world.proto`
pub mod error;
pub mod grpc;
mod r#impl;

use std::sync::Arc;

use futures::future::BoxFuture;
use serde::{Deserialize, Serialize};

use crate::prelude::IntoStatus;

pub use error::Error;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct Size {
pub width: u32,
Expand Down Expand Up @@ -78,5 +86,17 @@ pub trait ProvideWorldService: Send + Sync + 'static {
self.world_service().check_coordinate(ctx, req)
}

// TODO: build_server(this: Arc<Self>) -> WorldServiceServer<...>
fn build_server(this: Arc<Self>) -> WorldServiceServer<Self>
where
Self: Sized,
{
let service = grpc::ServiceImpl::new(this);
WorldServiceServer::new(service)
}
}

#[derive(Debug, Clone, Copy)]
pub struct WorldServiceImpl;

pub type WorldServiceServer<State> =
schema::world::world_service_server::WorldServiceServer<grpc::ServiceImpl<State>>;
11 changes: 11 additions & 0 deletions server/src/world/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// infallible
#[derive(Debug, Clone, thiserror::Error)]
pub enum Error {}

impl From<Error> for tonic::Status {
fn from(value: Error) -> Self {
match value {}
}
}

pub type Result<T, E = Error> = std::result::Result<T, E>;
84 changes: 84 additions & 0 deletions server/src/world/grpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::sync::Arc;

use schema::world as schema;

use crate::prelude::IntoStatus;

// MARK: type conversions

impl From<super::Coordinate> for schema::Coordinate {
fn from(value: super::Coordinate) -> Self {
let super::Coordinate { x, y } = value;
Self { x, y }
}
}

impl From<schema::Coordinate> for super::Coordinate {
fn from(value: schema::Coordinate) -> Self {
let schema::Coordinate { x, y } = value;
Self { x, y }
}
}

impl From<super::Size> for schema::Size {
fn from(value: super::Size) -> Self {
let super::Size { width, height } = value;
Self { width, height }
}
}

impl From<schema::Size> for super::Size {
fn from(value: schema::Size) -> Self {
let schema::Size { width, height } = value;
Self { width, height }
}
}

// MARK: ServiceImpl

pub struct ServiceImpl<State> {
state: Arc<State>,
}

impl<State> Clone for ServiceImpl<State>
where
State: super::ProvideWorldService,
{
fn clone(&self) -> Self {
Self {
state: Arc::clone(&self.state),
}
}
}

impl<State> ServiceImpl<State>
where
State: super::ProvideWorldService,
{
pub(super) fn new(state: Arc<State>) -> Self {
Self { state }
}
}

#[async_trait::async_trait]
impl<State> schema::world_service_server::WorldService for ServiceImpl<State>
where
State: super::ProvideWorldService,
{
async fn get_world(
&self,
request: tonic::Request<schema::GetWorldRequest>,
) -> tonic::Result<tonic::Response<schema::GetWorldResponse>> {
let (_, _, schema::GetWorldRequest {}) = request.into_parts();
let req = super::GetWorldSize {};
let size = self
.state
.get_world_size(req)
.await
.map_err(IntoStatus::into_status)?
.into();
let world = schema::World { size: Some(size) };
let res = schema::GetWorldResponse { world: Some(world) };
Ok(tonic::Response::new(res))
}
}
34 changes: 34 additions & 0 deletions server/src/world/impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use futures::{future, FutureExt};

impl<Context> super::WorldService<Context> for super::WorldServiceImpl
where
Context: super::WorldSizeStore,
{
type Error = super::Error;

fn get_world_size<'a>(
&'a self,
ctx: &'a Context,
req: super::GetWorldSize,
) -> future::BoxFuture<'a, Result<super::Size, Self::Error>> {
let super::GetWorldSize {} = req;
let size = ctx.world_size();
let fut = future::ready(Ok(size));
fut.boxed()
}

fn check_coordinate<'a>(
&'a self,
ctx: &'a Context,
req: super::CheckCoordinate,
) -> future::BoxFuture<'a, Result<super::CheckCoordinateAnswer, Self::Error>> {
let size = ctx.world_size();
let super::CheckCoordinate { coordinate } = req;
let res = if coordinate.x < size.width && coordinate.y < size.height {
super::CheckCoordinateAnswer::Valid(coordinate)
} else {
super::CheckCoordinateAnswer::Invalid
};
future::ready(Ok(res)).boxed()
}
}

0 comments on commit 383fde8

Please sign in to comment.