I am debugging the Parity Ethereum client with LLDB in VSCode and I am trying to access a value through several references.
Here is the code with relevant parts only (full code here)
pub struct SignedTransaction {
transaction: UnverifiedTransaction,
sender: Address,
public: Option<Public>,
}
impl Deref for SignedTransaction {
type Target = UnverifiedTransaction;
fn deref(&self) -> &Self::Target {
&self.transaction
}
}
pub struct UnverifiedTransaction {
unsigned: Transaction,
v: u64,
r: U256,
s: U256,
hash: H256,
}
impl Deref for UnverifiedTransaction {
type Target = Transaction;
fn deref(&self) -> &Self::Target {
&self.unsigned
}
}
pub struct Transaction {
pub nonce: U256,
pub gas_price: U256,
pub gas: U256,
pub action: Action,
pub value: U256,
pub data: Bytes,
}
pub enum Action {
Create,
Call(Address),
}
I have &SignedTransaction t with a value t.action = Action::Create (verified by manual print).
I am looking to get action value as VSCode shows a misleading value:
VSCode showing misleading value
I cannot manage to print only action value but the command p t.transaction outputs this (truncated) :
(ethcore_transaction::transaction::UnverifiedTransaction) $2 = {
unsigned = {
action = Call(((20) ['\', '!', '\xf6', '\xff', '\x7f', '\0', ...])) {
= Call(((20) ['\', '!', '\xf6', '\xff', '\x7f', '\0', ...])) {
RUST$ENUM$DISR = Create {...}
In the case where t.action = Action::Call() the value is correctly shown.
Why does it not show action = Create ? How can I print more cleanly action value ?
EDIT: the command fr v t->transaction.unsigned.action.RUST$ENUM$DISR shows the correct enum value. However I still don't know why fr v t->transaction.unsigned.action displays wrong values (which are also shown in the graphical interface).
Related
I've been trying to implement a Strategy pattern in rust, but I'm having trouble understanding how to make it work.
So let's imagine we have a trait Adder and Element:
pub trait Element {
fn to_string(&self) -> String;
}
pub trait Adder {
type E: Element;
fn add (&self, a: &Self::E, b: &Self::E) -> Self::E;
}
And we have two implementations StringAdder with StringElements and UsizeAdder with UsizeElements:
// usize
pub struct UsizeElement {
pub value: usize
}
impl Element for UsizeElement {
fn to_string(&self) -> String {
self.value.to_string()
}
}
pub struct UsizeAdder {
}
impl Adder for UsizeAdder{
type E = UsizeElement;
fn add(&self, a: &UsizeElement, b: &UsizeElement) -> UsizeElement{
UsizeElement { value: a.value + b.value }
}
}
// String
pub struct StringElement {
pub value: String
}
impl Element for StringElement {
fn to_string(&self) -> String {
self.value.to_string()
}
}
pub struct StringAdder {
}
impl Adder for StringAdder {
type E = StringElement;
fn add(&self, a: &StringElement, b: &StringElement) -> StringElement {
let a: usize = a.value.parse().unwrap();
let b: usize = b.value.parse().unwrap();
StringElement {
value: (a + b).to_string()
}
}
}
And I want to write a code that uses trait methods from Adder trait and it's corresponding elements without knowing at compile time which strategy is going to be used.
fn main() {
let policy = "usize";
let element = "1";
let adder = get_adder(&policy);
let element_a = get_element(&policy, element);
let result = adder.add(element_a, element_a);
}
To simplify I'm going to assign a string to policy and element but normally that would be read from a file.
Is the only way to implement get_adder and get_element using dynamic dispatch? And by extension should I define Adder and Element traits to use trait objects and or the Any trait?
Edit: Here is what I managed to figure out so far.
An example of possible implementation is using match to help define concrete types for the compiler.
fn main() {
let policy = "string";
let element = "1";
let secret_key = "5";
let result = cesar(policy, element, secret_key);
dbg!(result.to_string());
}
fn cesar(policy: &str, element: &str, secret_key: &str) -> Box<dyn Element>{
match policy {
"usize" => {
let adder = UsizeAdder{};
let element = UsizeElement{ value: element.parse().unwrap() };
let secret_key = UsizeElement{ value: secret_key.parse().unwrap() };
Box::new(cesar_impl(&adder, &element, &secret_key))
}
"string" => {
let adder = StringAdder{};
let element = StringElement{ value: element.to_string() };
let secret_key = StringElement{ value: secret_key.to_string() };
Box::new(cesar_impl(&adder, &element, &secret_key))
}
_ => {
panic!("Policy not supported!")
}
}
}
fn cesar_impl<A>(adder: &A, element: &A::E, secret_key: &A::E) -> A::E where A: Adder, A::E : Element {
adder.add(&element, &secret_key)
}
However the issue is that I have to wrap every function I want to implement using a match function to determine the concrete type, and also case for every policy available.
It does not seem like the proper way of implementing it as it will bloat the code, make it more error prone and less maintainable unless I end up using macros.
Edit 2: Here you can find an example using dynamic dispatch. However I'm not convinced it's the proper way to implement the solution.
Example using dynamic dispatch
Thank you for your help :)
I'm using the tracing library in my project and there is one thing I'm not able to figure out: How can I access a value (that I set in my span when I create it) in my Layer?
My layer looks like this:
impl<S> Layer<S> for CustomLayer where S: Subscriber {
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
Interest::sometimes() //hardcoding so enabled() will be called everytime a span is created
}
fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
if metadata.is_span() {
// How do I access value of key here?
if value == X {
true
} else if value == Y {
false
}
}
true // default
}
}
You can access the data in a Span if you have access to either its ValueSet (as found in new_span() or on_new_span() via Attributes) or a Record entry for it (as found in record() or on_record()). With that you can use the visitor pattern to find the information you desire. Here's a simple implementation that checks if a field exists and its value is a matching string:
use std::fmt::Debug;
use tracing::field::{ValueSet, Visit, Field};
use tracing::span::Record;
struct MatchStrVisitor<'a> {
field: &'a str,
value: &'a str,
matched: bool,
}
impl Visit for MatchStrVisitor<'_> {
fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {}
fn record_str(&mut self, field: &Field, value: &str) {
if field.name() == self.field && value == self.value {
self.matched = true;
}
}
}
fn value_in_valueset(valueset: &ValueSet<'_>, field: &str, value: &str) -> bool {
let mut visitor = MatchStrVisitor { field, value, matched: false };
valueset.record(&mut visitor);
visitor.matched
}
fn value_in_record(record: &Record<'_>, field: &str, value: &str) -> bool {
let mut visitor = MatchStrVisitor { field, value, matched: false };
record.record(&mut visitor);
visitor.matched
}
This is pretty rudimentary but hopefully demonstrates what is possible. One thing to note is that the "value" that is stored is either a primitive value (i64, u64, bool, str, etc.) or in a type-erased form via &dyn Debug. Those are the only types of values you can receive from the visitor.
Addressing OP's case in particular, as explained in this issue you cannot access this information in the enabled() method since that occurs before any values are recorded. You will need to make your determination in the new_span() method, and use span extensions via the registry to track whether you consider the span is "enabled" in your other methods.
Here's another rudimentary example:
use tracing::span::Attributes;
use tracing::{Subscriber, Metadata, Id, Event};
use tracing::subscriber::Interest;
use tracing_subscriber::layer::{Context, Layer};
use tracing_subscriber::registry::LookupSpan;
struct CustomLayer;
struct CustomLayerEnabled;
impl<S> Layer<S> for CustomLayer where S: Subscriber + for <'a> LookupSpan<'a> {
fn register_callsite(&self, _metadata: &'static Metadata<'static>) -> Interest {
Interest::sometimes()
}
fn enabled(&self, metadata: &Metadata<'_>, _ctx: Context<'_, S>) -> bool {
metadata.is_span()
}
fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
if value_in_valueset(attrs.values(), "myfield", "myvalue") {
ctx.span(id).unwrap().extensions_mut().insert(CustomLayerEnabled);
}
}
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
let span_id = event.parent().unwrap();
if let None = ctx.span(span_id).unwrap().extensions().get::<CustomLayerEnabled>() {
return;
}
// ... rest of your logic
}
}
Note: I've completely rewritten this answer taking info from the comments and my newfound experience.
Example:
let response = add_customer(InputCustomer)
.validate()?
.generate_code()
.create(DB::create(pool_conextion))?;
I tried using various structures, but I don't know if it is the best way to do it:
struct InputCustomer {}
fn add_customer(i: InputCustomer) -> Validate {
Validate {
result: InputCustomer {},
}
}
struct Validate {
result: InputCustomer,
}
impl Validate {
fn do_validate() -> GenCode {
// valdiate struct customer
GenCode {
result: InputCustomer {},
}
}
}
struct GenCode {
result: InputCustomer,
}
impl GenCode {
fn generate_code() -> Create {
// generate customer code
Create { result: true }
}
}
struct Create {
result: bool,
}
You can implement all the functions on a single struct using phantom type parameters. The Customer struct holds some state:
pub struct Customer<State> {
state: PhantomData<State>,
}
We can create the possible states that a Customer can be in:
pub struct CustomerStateNew;
pub struct CustomerStateValidated;
pub struct CustomerStateWithCode;
When you create a Customer, it's state is CustomerStateNew:
pub fn add_customer() -> Customer<CustomerStateNew> {
Customer { state: PhantomData }
}
To validate a Customer it must be in the CustomerStateNew state:
impl Customer<CustomerStateNew> {
pub fn validate(&self) -> Customer<CustomerStateValidated> {
Customer { state: PhantomData }
}
}
The Customer must be validated (CustomerStateValidated) to generate a code:
impl Customer<CustomerStateValidated> {
pub fn generate_code(&self) -> Customer<CustomerStateWithCode> {
Customer { state: PhantomData }
}
}
And it must have a generated code (CustomerStateWithCode) to be created. create consumes self, so the customer cannot be used after it is created (you might not want this behavior, but I included it here for completeness):
impl Customer<CustomerStateWithCode> {
pub fn create(self) -> Result<(), ()> {
Ok(())
}
}
Now we can chain together the methods to create the user:
let result = add_customer().validate().generate_code().create()?;
However, it we try to create the Customer before it is validated, the code will not compile:
let result = add_customer().create();
// error[E0599]: no method named `create` found for struct `Customer<CustomerStateNew>`
// --> src/main.rs:36:20
// 36 | add_customer().create();
// | ^^^^^^ method not found in `Customer<CustomerStateNew>`
Also, no one else can create a Customer with an arbitrary state, because the state field is private:
mod somewhere_else {
fn bla() {
let customer: Customer<CustomerStateWithCode> = Customer { state: PhantomData };
customer.create();
}
}
// error[E0451]: field `state` of struct `Customer` is private
// --> src/main.rs:41:64
// |
// 41 | let customer: Customer<CustomerStateWithCode> = Customer { state: PhantomData };
// |
If you want to store data specific to each state, you can store that actual State inside the Customer instead of PhantomData. Now however, the state is more than just compile time safety and will be stored at runtime:
pub struct CustomerStateWithCode(pub usize);
pub struct Customer<State> {
state: State,
}
impl Customer<CustomerStateValidated> {
pub fn generate_code(&self) -> Customer<CustomerStateWithCode> {
Customer { state: CustomerStateWithCode(1234) }
}
}
We have created a simple state machine using phantom types. This is also knows as the type state pattern. Note that the states will be compiled away to nothing, so there is no runtime cost, only compile time safety!
Playground link
I'm trying to create a method that can return a reference to Data that is either in a constant global array or inside an Option in an item. The lifetimes are certainly different, but it's safe to assume that the lifetime of the data is at least as long as the lifetime of the item. While doing this, I expected the compiler to warn if I did anything wrong, but it's instead generating wrong instructions and the program is crashing with SIGILL.
Concretely speaking, I have the following code failing in Rust 1.27.2:
#[derive(Debug)]
pub enum Type {
TYPE1,
TYPE2,
}
#[derive(Debug)]
pub struct Data {
pub ctype: Type,
pub int: i32,
}
#[derive(Debug)]
pub struct Entity {
pub idata: usize,
pub modifier: Option<Data>,
}
impl Entity {
pub fn data(&self) -> &Data {
if self.modifier.is_none() {
&DATA[self.idata]
} else {
self.modifier.as_ref().unwrap()
}
}
}
pub const DATA: [Data; 1] = [Data {
ctype: Type::TYPE2,
int: 1,
}];
fn main() {
let mut itemvec = vec![Entity {
idata: 0,
modifier: None,
}];
eprintln!("vec[0]: {:p} = {:?}", &itemvec[0], itemvec[0]);
eprintln!("removed item 0");
let item = itemvec.remove(0);
eprintln!("item: {:p} = {:?}", &item, item);
eprintln!("modifier: {:p} = {:?}", &item.modifier, item.modifier);
eprintln!("DATA: {:p} = {:?}", &DATA[0], DATA[0]);
let itemdata = item.data();
eprintln!("itemdata: {:p} = {:?}", itemdata, itemdata);
}
Complete code
I can't understand what I'm doing wrong. Why isn't the compiler generating a warning? Is it the removal of the (non-copy) item of the vector? Is it the ambiguous lifetimes?
How to return a reference to a global vector or an internal Option?
By using Option::unwrap_or_else:
impl Entity {
pub fn data(&self) -> &Data {
self.modifier.as_ref().unwrap_or_else(|| &DATA[self.idata])
}
}
but it's instead generating wrong instructions and the program is crashing with SIGILL
The code in your question does not have this behavior on macOS with Rust 1.27.2 or 1.28.0. On Ubuntu I see an issue when running the program in Valgrind, but the problem goes away in Rust 1.28.0.
See also:
Why should I prefer `Option::ok_or_else` instead of `Option::ok_or`?
What is this unwrap thing: sometimes it's unwrap sometimes it's unwrap_or
Here's where I'm starting from:
#[derive(PartialEq)]
enum ControlItem {
A {
name: &'static str,
},
B {
name: &'static str,
},
}
struct Control {
items: Vec<(ControlItem, bool)>,
}
impl Control {
pub fn set(&mut self, item: ControlItem, is_ok: bool) {
match self.items.iter().position(|ref x| (**x).0 == item) {
Some(idx) => {
self.items[idx].1 = is_ok;
}
None => {
self.items.push((item, is_ok));
}
}
}
pub fn get(&self, item: ControlItem) -> bool {
match self.items.iter().position(|ref x| (**x).0 == item) {
Some(idx) => return self.items[idx].1,
None => return false,
}
}
}
fn main() {
let mut ctrl = Control { items: vec![] };
ctrl.set(ControlItem::A { name: "a" }, true);
assert_eq!(ctrl.get(ControlItem::A { name: "a" }), true);
ctrl.set(ControlItem::B { name: "b" }, false);
assert_eq!(ctrl.get(ControlItem::B { name: "b" }), false);
}
I have a Control type that should save the state of some predefined items and report it back to user.
I have a virtual table in my mind, like this:
|Name in program | Name for user |
|item_1 | Item one bla-bla |
|item_2 | Item two bla-bla |
|item_3 | Item three another-bla-bla|
I want Control to have get / set methods that accept only things with names item_1, item_2, item_3.
I want to hold this virtual table in two crates: "main" and "platform". Most of the implementation of Control should be in the main crate, and definitions of the items (like item_3) should go into the platform crate. I want to register item_3 at compile time.
Any ideas on how achieve this?
It sounds like you should use a trait, not an enum. You could define a trait and implement it like this:
pub trait ControlItem {
fn name(&self) -> &str;
}
struct A(&'static str);
impl ControlItem for A {
fn name(&self) -> &str {
self.0
}
}
// ... similar struct and impl blocks for other items
Then these structs can be moved into separate crates.
You'd need to change Control to store a Vec<(Box<ControlItem>, bool)>, and either change get and set to take a Box<ControlItem>, or to be generic over T: ControlItem.
Read about traits and trait objects for more.