diff --git a/conversations/src/api.rs b/conversations/src/api.rs index d8eb367..62d635c 100644 --- a/conversations/src/api.rs +++ b/conversations/src/api.rs @@ -49,8 +49,15 @@ pub struct ContextHandle(pub(crate) Context); /// # Returns /// Opaque handle to the store. Must be freed with destroy_context() #[ffi_export] -pub fn create_context() -> repr_c::Box { - Box::new(ContextHandle(Context::new())).into() +pub fn create_context(name: repr_c::String) -> repr_c::Box { + // Deference name to to `str` and then borrow to &str + Box::new(ContextHandle(Context::new_with_name(&*name))).into() +} + +/// Returns the friendly name of the contexts installation. +#[ffi_export] +pub fn installation_name(ctx: &ContextHandle) -> repr_c::String { + ctx.0.installation_name().to_string().into() } /// Destroys a conversation store and frees its memory diff --git a/conversations/src/context.rs b/conversations/src/context.rs index 3e16386..44dbce5 100644 --- a/conversations/src/context.rs +++ b/conversations/src/context.rs @@ -21,8 +21,8 @@ pub struct Context { } impl Context { - pub fn new() -> Self { - let identity = Rc::new(Identity::new()); + pub fn new_with_name(name: impl Into) -> Self { + let identity = Rc::new(Identity::new(name)); let inbox = Inbox::new(Rc::clone(&identity)); // Self { _identity: identity, @@ -31,6 +31,10 @@ impl Context { } } + pub fn installation_name(&self) -> &str { + self._identity.get_name() + } + pub fn create_private_convo( &mut self, remote_bundle: &Introduction, @@ -156,8 +160,8 @@ mod tests { #[test] fn ctx_integration() { - let mut saro = Context::new(); - let mut raya = Context::new(); + let mut saro = Context::new_with_name("saro"); + let mut raya = Context::new_with_name("raya"); // Raya creates intro bundle and sends to Saro let bundle = raya.create_intro_bundle().unwrap(); diff --git a/conversations/src/identity.rs b/conversations/src/identity.rs index de3be1e..76c2700 100644 --- a/conversations/src/identity.rs +++ b/conversations/src/identity.rs @@ -3,6 +3,7 @@ use std::fmt; use crate::crypto::{PrivateKey, PublicKey}; pub struct Identity { + name: String, secret: PrivateKey, } @@ -16,8 +17,9 @@ impl fmt::Debug for Identity { } impl Identity { - pub fn new() -> Self { + pub fn new(name: impl Into) -> Self { Self { + name: name.into(), secret: PrivateKey::random(), } } @@ -29,10 +31,17 @@ impl Identity { pub fn secret(&self) -> &PrivateKey { &self.secret } + + // Returns an associated name for this Identity. + // Names are a friendly developer chosen identifier for an Identity which + // can provide between logging. + pub fn get_name(&self) -> &str { + &self.name + } } impl Default for Identity { fn default() -> Self { - Self::new() + Self::new("default") } } diff --git a/conversations/src/inbox/handler.rs b/conversations/src/inbox/handler.rs index f953cca..278ae16 100644 --- a/conversations/src/inbox/handler.rs +++ b/conversations/src/inbox/handler.rs @@ -238,10 +238,10 @@ mod tests { #[test] fn test_invite_privatev1_roundtrip() { - let saro_ident = Identity::new(); + let saro_ident = Identity::new("saro"); let saro_inbox = Inbox::new(saro_ident.into()); - let raya_ident = Identity::new(); + let raya_ident = Identity::new("raya"); let mut raya_inbox = Inbox::new(raya_ident.into()); let bundle = raya_inbox.create_intro_bundle(); diff --git a/conversations/src/lib.rs b/conversations/src/lib.rs index 8ae1d51..810afb9 100644 --- a/conversations/src/lib.rs +++ b/conversations/src/lib.rs @@ -21,8 +21,8 @@ mod tests { #[test] fn test_message_roundtrip() { - let mut saro = create_context(); - let mut raya = create_context(); + let mut saro = create_context("saro".into()); + let mut raya = create_context("raya".into()); // Raya Creates Bundle and Sends to Saro let intro_result = create_intro_bundle(&mut raya); diff --git a/nim-bindings/.gitignore b/nim-bindings/.gitignore new file mode 100644 index 0000000..f3685e2 --- /dev/null +++ b/nim-bindings/.gitignore @@ -0,0 +1,3 @@ +nimble.develop +nimble.paths +nimbledeps diff --git a/nim-bindings/config.nims b/nim-bindings/config.nims new file mode 100644 index 0000000..8ee48d2 --- /dev/null +++ b/nim-bindings/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 2) +when withDir(thisDir(), system.fileExists("nimble.paths")): + include "nimble.paths" +# end Nimble config diff --git a/nim-bindings/examples/pingpong.nim b/nim-bindings/examples/pingpong.nim index 339e5e6..3c7dfdc 100644 --- a/nim-bindings/examples/pingpong.nim +++ b/nim-bindings/examples/pingpong.nim @@ -15,8 +15,8 @@ proc encode*(s: string): seq[byte] = proc pingpong() = - var raya = newConversationsContext() - var saro = newConversationsContext() + var raya = newConversationsContext("raya") + var saro = newConversationsContext("saro") # Perform out of band Introduction diff --git a/nim-bindings/src/bindings.nim b/nim-bindings/src/bindings.nim index a03d5d2..cb64247 100644 --- a/nim-bindings/src/bindings.nim +++ b/nim-bindings/src/bindings.nim @@ -97,7 +97,11 @@ type ## Creates a new libchat Context ## Returns: Opaque handle to the context. Must be freed with destroy_context() -proc create_context*(): ContextHandle {.importc, dynlib: CONVERSATIONS_LIB.} +proc create_context*(name: ReprCString): ContextHandle {.importc, dynlib: CONVERSATIONS_LIB.} + +## Returns the friendly name of the context's identity +## The result must be freed by the caller (repr_c::String ownership transfers) +proc installation_name*(ctx: ContextHandle): ReprCString {.importc, dynlib: CONVERSATIONS_LIB.} ## Destroys a context and frees its memory ## - handle must be a valid pointer from create_context() diff --git a/nim-bindings/src/libchat.nim b/nim-bindings/src/libchat.nim index c9a5b1b..9b2cb0e 100644 --- a/nim-bindings/src/libchat.nim +++ b/nim-bindings/src/libchat.nim @@ -13,13 +13,20 @@ type data*: seq[uint8] ## Create a new conversations context -proc newConversationsContext*(): LibChat = +proc newConversationsContext*(name: string): LibChat = - result.handle = create_context() + result.handle = create_context(name.toReprCString) result.buffer_size = 256 if result.handle.isNil: raise newException(IOError, "Failed to create context") +## Get the friendly name of this context's installation +proc getInstallationName*(ctx: LibChat): string = + if ctx.handle == nil: + return "" + let name = installation_name(ctx.handle) + result = $name + ## Destroy the context and free resources proc destroy*(ctx: var LibChat) =