| // Copyright 2023 Google LLC | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | use crate::{central::ScanResult, client::CharacteristicNotification, types::*}; | 
 |  | 
 | use bt_common::{PeerId, Uuid}; | 
 | use futures::{future::Ready, stream::Empty, Future, Stream}; | 
 | use std::task::Poll; | 
 |  | 
 | #[derive(Default)] | 
 | pub(crate) struct FakeCentral {} | 
 |  | 
 | pub(crate) struct FakePeerService {} | 
 |  | 
 | impl crate::client::PeerService for FakePeerService { | 
 |     type CharacteristicsFut = Ready<Result<Vec<Characteristic>>>; | 
 |     type NotificationStream = Empty<Result<CharacteristicNotification>>; | 
 |     type ReadFut<'a> = Ready<Result<(usize, bool)>>; | 
 |     type WriteFut<'a> = Ready<Result<()>>; | 
 |  | 
 |     fn discover_characteristics(&self, _uuid: Option<Uuid>) -> Self::CharacteristicsFut { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn read_characteristic<'a>( | 
 |         &self, | 
 |         _handle: &Handle, | 
 |         _offset: u16, | 
 |         _buf: &'a mut [u8], | 
 |     ) -> Self::ReadFut<'a> { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn write_characteristic<'a>( | 
 |         &self, | 
 |         _handle: &Handle, | 
 |         _mode: WriteMode, | 
 |         _offset: u16, | 
 |         _buf: &'a [u8], | 
 |     ) -> Self::WriteFut<'a> { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn read_descriptor<'a>( | 
 |         &self, | 
 |         _handle: &Handle, | 
 |         _offset: u16, | 
 |         _buf: &'a mut [u8], | 
 |     ) -> Self::ReadFut<'a> { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn write_descriptor<'a>( | 
 |         &self, | 
 |         _handle: &Handle, | 
 |         _offset: u16, | 
 |         _buf: &'a [u8], | 
 |     ) -> Self::WriteFut<'a> { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn subscribe(&self, _handle: &Handle) -> Self::NotificationStream { | 
 |         todo!() | 
 |     } | 
 | } | 
 |  | 
 | pub(crate) struct FakeServiceHandle {} | 
 |  | 
 | impl crate::client::PeerServiceHandle for FakeServiceHandle { | 
 |     type PeerServiceT = FakePeerService; | 
 |     type ConnectFut = Ready<Result<Self::PeerServiceT>>; | 
 |  | 
 |     fn uuid(&self) -> Uuid { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn is_primary(&self) -> bool { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn connect(&self) -> Self::ConnectFut { | 
 |         todo!() | 
 |     } | 
 | } | 
 |  | 
 | pub(crate) struct FakeClient {} | 
 |  | 
 | impl crate::Client for FakeClient { | 
 |     type PeerServiceHandleT = FakeServiceHandle; | 
 |     type ServiceResultFut = Ready<Result<Vec<Self::PeerServiceHandleT>>>; | 
 |  | 
 |     fn peer_id(&self) -> PeerId { | 
 |         todo!() | 
 |     } | 
 |  | 
 |     fn find_service(&self, _uuid: Uuid) -> Self::ServiceResultFut { | 
 |         todo!() | 
 |     } | 
 | } | 
 |  | 
 | pub(crate) struct SingleResultStream { | 
 |     result: Option<Result<crate::central::ScanResult>>, | 
 | } | 
 |  | 
 | impl Stream for SingleResultStream { | 
 |     type Item = Result<crate::central::ScanResult>; | 
 |  | 
 |     fn poll_next( | 
 |         self: std::pin::Pin<&mut Self>, | 
 |         _cx: &mut std::task::Context<'_>, | 
 |     ) -> Poll<Option<Self::Item>> { | 
 |         if self.result.is_some() { | 
 |             Poll::Ready(self.get_mut().result.take()) | 
 |         } else { | 
 |             // Never wake up, as if we never find another result | 
 |             Poll::Pending | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | pub(crate) struct ClientConnectFut {} | 
 |  | 
 | impl Future for ClientConnectFut { | 
 |     type Output = Result<FakeClient>; | 
 |  | 
 |     fn poll( | 
 |         self: std::pin::Pin<&mut Self>, | 
 |         _cx: &mut std::task::Context<'_>, | 
 |     ) -> Poll<Self::Output> { | 
 |         todo!() | 
 |     } | 
 | } | 
 |  | 
 | impl crate::Central for FakeCentral { | 
 |     type ScanResultStream = SingleResultStream; | 
 |  | 
 |     type Client = FakeClient; | 
 |  | 
 |     type ClientFut = ClientConnectFut; | 
 |  | 
 |     fn scan(&self, _filters: &[crate::central::ScanFilter]) -> Self::ScanResultStream { | 
 |         SingleResultStream { | 
 |             result: Some(Ok(ScanResult { | 
 |                 id: PeerId(1), | 
 |                 connectable: true, | 
 |                 name: crate::central::PeerName::CompleteName("Marie's Pixel 7 Pro".to_owned()), | 
 |                 advertised: vec![crate::central::AdvertisingDatum::Services(vec![ | 
 |                     Uuid::from_u16(0x1844), | 
 |                 ])], | 
 |             })), | 
 |         } | 
 |     } | 
 |  | 
 |     fn connect(&self, _peer_id: PeerId) -> Self::ClientFut { | 
 |         todo!() | 
 |     } | 
 | } | 
 |  | 
 | #[test] | 
 | fn central_search_works() { | 
 |     use crate::Central; | 
 |     use futures::StreamExt; | 
 |  | 
 |     let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref()); | 
 |     use crate::central::Filter; | 
 |     let central = FakeCentral::default(); | 
 |  | 
 |     let mut scan_results = central.scan(&[Filter::ServiceUuid(Uuid::from_u16(0x1844)).into()]); | 
 |  | 
 |     let polled = scan_results.poll_next_unpin(&mut noop_cx); | 
 |     let Poll::Ready(Some(Ok(_scan_result))) = polled else { | 
 |         panic!("Expected a ready scan result got {polled:?}"); | 
 |     }; | 
 | } |