Guest User

Untitled

a guest
Oct 17th, 2018
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.12 KB | None | 0 0
  1. // Sorry, if this is a bit messy, I will try my best to explain
  2. // what is going on:
  3. // I am creating a recursive type to keep track of the transaction.
  4. // This should allow the compiler to optimize most of the overhead
  5. // away and does not rely on std or the use of an internal buffer.
  6.  
  7. /// A single transaction step
  8. #[derive(Debug)]
  9. enum Step<'a> {
  10. Write(&'a [u8]),
  11. Read(&'a mut [u8]),
  12. }
  13.  
  14. /// Marker for the end of the transaction list
  15. #[derive(Debug)]
  16. struct End;
  17.  
  18. /// Type for the recursive step list
  19. ///
  20. /// In practice, the types will look like
  21. /// TStep(Step::Write(..), TStep(Step::Read(..), End))
  22. #[derive(Debug)]
  23. struct TStep<A, B>(A, B);
  24.  
  25. /// A transactable transaction. The idea is that a type that implements
  26. /// this trait is given to the bus to perform the transaction.
  27. /// The bus can then call `transact` to iterate over the steps.
  28. trait Transact<'a> {
  29. fn transact<F: FnMut(&mut Step<'a>)>(&'a mut self, f: F) -> F;
  30. }
  31.  
  32. // Implementation for the last step
  33. impl<'a> Transact<'a> for TStep<Step<'a>, End> {
  34. fn transact<F: FnMut(&mut Step<'a>)>(&'a mut self, mut f: F) -> F {
  35. f(&mut self.0);
  36. f
  37. }
  38. }
  39.  
  40. // Implementation for not last steps, calls transact recursively
  41. //
  42. // Needs to be depth first, because the list is backwards. I am unsure
  43. // if this can be done differently.
  44. impl<'a, S: Transact<'a>> Transact<'a> for TStep<Step<'a>, S> {
  45. fn transact<F: FnMut(&mut Step<'a>)>(&'a mut self, f: F) -> F {
  46. let mut f = self.1.transact(f);
  47. f(&mut self.0);
  48. f
  49. }
  50. }
  51.  
  52. ////////////////////////////////////////////////////////////////////////////
  53. ////////////////////////////////////////////////////////////////////////////
  54. // NEW //
  55. ////////////////////////////////////////////////////////////////////////////
  56. ////////////////////////////////////////////////////////////////////////////
  57. impl<'a, T: std::iter::Iterator<Item = &'a mut Step<'a>>> Transact<'a> for T {
  58. fn transact<F: FnMut(&mut Step<'a>)>(&'a mut self, mut f: F) -> F {
  59. for mut s in self {
  60. f(s);
  61. }
  62. f
  63. }
  64. }
  65.  
  66. /// A transaction that is bound to a bus and an address
  67. ///
  68. /// While the transaction is being created, it takes a mutable
  69. /// reference to the bus and only releases it once the transaction
  70. /// is done (goes out of scope).
  71. #[derive(Debug)]
  72. struct Transaction<'a, B: Transactor + 'a, S> {
  73. addr: u8,
  74. bus: &'a mut B,
  75. steps: S,
  76. }
  77.  
  78. impl<'a, B: Transactor + 'a, S> Transaction<'a, B, S> {
  79. /// Add a new write step using the Builder pattern
  80. pub fn write(self, data: &'a [u8]) -> Transaction<'a, B, TStep<Step<'a>, S>> {
  81. println!(" Adding write for {} bytes", data.len());
  82.  
  83. Transaction {
  84. addr: self.addr,
  85. bus: self.bus,
  86. steps: TStep(Step::Write(data), self.steps),
  87. }
  88. }
  89.  
  90. /// Add a new read step using the Builder pattern
  91. pub fn read(self, buf: &'a mut [u8]) -> Transaction<'a, B, TStep<Step<'a>, S>> {
  92. println!(" Adding read for {} bytes", buf.len());
  93.  
  94. Transaction {
  95. addr: self.addr,
  96. bus: self.bus,
  97. steps: TStep(Step::Read(buf), self.steps),
  98. }
  99. }
  100. }
  101.  
  102. impl<'a, B: Transactor + 'a, S: Transact<'a>> Transaction<'a, B, S> {
  103. /// Commit this transaction
  104. ///
  105. /// Can only be called if the transaction contains transactable steps
  106. /// (= called .write() or .read() at least once)
  107. pub fn commit(&'a mut self) -> Result<(), ()> {
  108. println!("Committing transaction!");
  109.  
  110. self.bus.commit(&mut self.steps)
  111. }
  112. }
  113.  
  114. /// This is the trait that your Bus type needs to implement.
  115. /// It provides the `transaction` method which a user will call to start
  116. /// a transaction. `commit` needs to be implemented by the bus and should
  117. /// perform the transaction. It is not usually called directly by a user.
  118. ///
  119. /// `shared-bus` could provide a blanket implementation for this trait
  120. trait Transactor: Sized {
  121. /// Start a new transaction for an address
  122. fn transaction<'a>(&'a mut self, addr: u8) -> Transaction<Self, End> {
  123. println!("Starting transaction ...");
  124.  
  125. Transaction {
  126. addr,
  127. bus: self,
  128. steps: End,
  129. }
  130. }
  131.  
  132. /// Commit, ie actually perform a transaction
  133. fn commit<'a, S: Transact<'a>>(&'a mut self, steps: &'a mut S) -> Result<(), ()>;
  134. }
  135.  
  136. /// Example bus type
  137. #[derive(Debug)]
  138. struct Bus;
  139.  
  140. // Example `Transactor` implementation
  141. impl Transactor for Bus {
  142. fn commit<'a, S: Transact<'a>>(&'a mut self, steps: &'a mut S) -> Result<(), ()> {
  143. let mut i = 0;
  144. println!(" I2C: Start");
  145. // The closure is called for each step of the transaction
  146. steps.transact(|s| match s {
  147. Step::Write(d) => println!(" I2C: Write {:?}", d),
  148. Step::Read(buf) => {
  149. println!(" I2C: Read {:?} bytes", buf.len());
  150. for b in buf.iter_mut() {
  151. *b = i;
  152. i += 1;
  153. }
  154. }
  155. });
  156. println!(" I2C: End");
  157. Ok(())
  158. }
  159. }
  160.  
  161. // Example
  162. fn main() {
  163. let mut bus = Bus;
  164. let mut buf1 = [0x00; 8];
  165. let mut buf2 = [0x00; 8];
  166.  
  167. bus.transaction(0x48)
  168. .write(&[0xde, 0xad, 0xbe, 0xef])
  169. .read(&mut buf1)
  170. .write(&[0xc0, 0xff, 0xee])
  171. .read(&mut buf2)
  172. .commit().unwrap();
  173.  
  174. println!("Take a look at the results:");
  175. println!(" Buf1: {:?}", buf1);
  176. println!(" Buf2: {:?}", buf2);
  177.  
  178. ////////////////////////////////////////////////////////////////////////////
  179. ////////////////////////////////////////////////////////////////////////////
  180. // NEW //
  181. ////////////////////////////////////////////////////////////////////////////
  182. ////////////////////////////////////////////////////////////////////////////
  183. println!("Example using a slice:");
  184.  
  185. bus.commit(&mut [
  186. Step::Write(&[0x35, 0xc3]),
  187. Step::Read(&mut buf1),
  188. Step::Write(&[0x35, 0xc3]),
  189. ].iter_mut()).unwrap();
  190.  
  191. println!("Take a look at the results:");
  192. println!(" Buf1: {:?}", buf1);
  193. }
Add Comment
Please, Sign In to add comment