pub mod client;
mod node;
pub mod server;
mod service;
use seahash::hash;
use std::fmt::Display;
use std::net::SocketAddr;
pub use client::Client;
pub use service::NodeService;
pub use service::error;
#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Debug, Eq, Hash)]
pub struct NodeId(u64);
impl From<SocketAddr> for NodeId {
fn from(addr: SocketAddr) -> Self {
Self(hash(addr.to_string().as_bytes()))
}
}
impl From<String> for NodeId {
fn from(key: String) -> Self {
Self(hash(key.as_bytes()))
}
}
impl Into<u64> for NodeId {
fn into(self) -> u64 {
self.0
}
}
impl From<u64> for NodeId {
fn from(id: u64) -> Self {
Self(id)
}
}
impl Display for NodeId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct Node {
id: NodeId,
addr: SocketAddr,
}
impl Node {
pub fn new(addr: SocketAddr) -> Self {
Self {
id: addr.into(),
addr,
}
}
pub fn addr(&self) -> SocketAddr {
self.addr
}
pub fn with_id(id: impl Into<NodeId>, addr: SocketAddr) -> Self {
Self {
id: id.into(),
addr,
}
}
pub fn id(&self) -> NodeId {
self.id
}
pub fn is_between_on_ring(id: u64, node1: u64, node2: u64) -> bool {
if node1 < node2 {
node1 < id && id <= node2
} else {
node1 < id || id <= node2
}
}
pub fn is_between_on_ring_exclusive(id: u64, node1: u64, node2: u64) -> bool {
if node1 < node2 {
node1 < id && id < node2
} else {
node1 < id || id < node2
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_between() {
assert_eq!(Node::is_between_on_ring(10, 5, 5), true);
assert_eq!(Node::is_between_on_ring(1, 5, 5), true);
assert_eq!(Node::is_between_on_ring(10, 5, 1), true);
assert_eq!(Node::is_between_on_ring(5, 5, 5), true);
assert_eq!(Node::is_between_on_ring(4, 1, 5), true);
assert_eq!(Node::is_between_on_ring(5, 1, 5), true);
assert_eq!(Node::is_between_on_ring(1, 1, 5), false);
assert_eq!(Node::is_between_on_ring(1, 2, 5), false);
}
#[test]
fn test_is_between_exclusive() {
assert_eq!(Node::is_between_on_ring_exclusive(10, 5, 5), true);
assert_eq!(Node::is_between_on_ring_exclusive(1, 5, 5), true);
assert_eq!(Node::is_between_on_ring_exclusive(10, 5, 1), true);
assert_eq!(Node::is_between_on_ring_exclusive(5, 5, 5), false);
assert_eq!(Node::is_between_on_ring_exclusive(4, 1, 5), true);
assert_eq!(Node::is_between_on_ring_exclusive(5, 1, 5), false);
assert_eq!(Node::is_between_on_ring_exclusive(1, 1, 5), false);
assert_eq!(Node::is_between_on_ring_exclusive(1, 2, 5), false);
}
}