bb_ops/syscalls/peers/
insert_many.rs1use bb_ir::proto::onnx::NodeProto;
13use bb_runtime::atomic::DispatchResult;
14use bb_runtime::bus::{OpError, OpErrorKind};
15use bb_runtime::framework::Address;
16use bb_runtime::ids::PeerId;
17use bb_runtime::runtime::RuntimeResourceRef;
18use bb_runtime::slot_value::SlotValue;
19use bb_runtime::syscall::values::{AddressVecValue, PeerIdValue};
20
21pub const DOMAIN: &str = "ai.bytesandbrains.address_book";
23pub const OP_TYPE: &str = "InsertMany";
25
26pub fn invoke(
34 _node: &NodeProto,
35 inputs: &[(&str, &dyn SlotValue)],
36 ctx: &mut RuntimeResourceRef<'_>,
37) -> Result<DispatchResult, OpError> {
38 let peer = downcast_peer(inputs)?;
39 let addresses = downcast_addresses(inputs)?;
40 if addresses.is_empty() {
41 return Err(OpError {
42 kind: OpErrorKind::ExecutionFailed,
43 reason: "address_book_insert_many_empty",
44 detail: "AddressBook::InsertMany: input `addresses` is empty".into(),
45 });
46 }
47 let result = if ctx.peers.addresses.lookup(peer).is_some() {
48 let mut last = Ok(());
49 for addr in addresses {
50 last = ctx.peers.addresses.register_address(peer, addr);
51 if last.is_err() {
52 break;
53 }
54 }
55 last
56 } else {
57 ctx.peers.addresses.add_peer(peer, addresses)
58 };
59 match result {
60 Ok(()) => Ok(DispatchResult::Immediate(Vec::new())),
61 Err(e) => Err(OpError {
62 kind: OpErrorKind::ExecutionFailed,
63 reason: "address_book_insert_many_failed",
64 detail: format!("AddressBook::InsertMany: {e}"),
65 }),
66 }
67}
68
69fn downcast_peer(inputs: &[(&str, &dyn SlotValue)]) -> Result<PeerId, OpError> {
70 let (_, value) = inputs
71 .iter()
72 .find(|(n, _)| *n == "peer")
73 .ok_or_else(|| OpError {
74 kind: OpErrorKind::MissingSlot,
75 reason: "missing_peer",
76 detail: "AddressBook::InsertMany: required input `peer` is absent".into(),
77 })?;
78 value
79 .as_any()
80 .downcast_ref::<PeerIdValue>()
81 .map(|p| p.0)
82 .ok_or_else(|| OpError {
83 kind: OpErrorKind::TypeMismatch,
84 reason: "expected_peer_id",
85 detail: "AddressBook::InsertMany: input `peer` is not a PeerId".into(),
86 })
87}
88
89fn downcast_addresses(inputs: &[(&str, &dyn SlotValue)]) -> Result<Vec<Address>, OpError> {
90 let (_, value) = inputs
91 .iter()
92 .find(|(n, _)| *n == "addresses")
93 .ok_or_else(|| OpError {
94 kind: OpErrorKind::MissingSlot,
95 reason: "missing_addresses",
96 detail: "AddressBook::InsertMany: required input `addresses` is absent".into(),
97 })?;
98 value
99 .as_any()
100 .downcast_ref::<AddressVecValue>()
101 .map(|a| a.0.clone())
102 .ok_or_else(|| OpError {
103 kind: OpErrorKind::TypeMismatch,
104 reason: "expected_address_vec",
105 detail: "AddressBook::InsertMany: input `addresses` is not an AddressVec".into(),
106 })
107}
108
109
110bb_derive::register_op! {
111 domain: "ai.bytesandbrains.address_book",
112 op_type: "InsertMany",
113 invoke: invoke,
114}