1+ // 21_validating_references_impl.rs
2+
3+ // 1. The Trait Definition (Required context)
4+ trait Parse < ' a > {
5+ fn parse ( input : & ' a str ) -> Self ;
6+ }
7+
8+ // 2. The Struct with References
9+ // We declare <'a> to tell the compiler:
10+ // "address" and "port" are strictly tied to the lifetime 'a.
11+ #[ derive( Debug ) ]
12+ struct ServerConfig < ' a > {
13+ address : & ' a str ,
14+ port : & ' a str ,
15+ }
16+
17+ // 3. The Implementation
18+ // This line is often tricky for beginners. We have three 'a usages:
19+ // 1. impl<'a>: We declare the lifetime generic for this block.
20+ // 2. Parse<'a>: We are implementing the version of Parse tied to 'a.
21+ // 3. ServerConfig<'a>: We are implementing it for the struct tied to 'a.
22+ impl < ' a > Parse < ' a > for ServerConfig < ' a > {
23+ fn parse ( input : & ' a str ) -> Self {
24+ // A very simple parser that splits by space.
25+ // Note: split(' ') returns an iterator yielding slices of the original string.
26+ // No new memory is allocated for the address or port strings!
27+ let mut parts = input. split ( ' ' ) ;
28+
29+ ServerConfig {
30+ address : parts. next ( ) . unwrap_or ( "localhost" ) ,
31+ port : parts. next ( ) . unwrap_or ( "8080" ) ,
32+ }
33+ }
34+ }
35+
36+ fn main ( ) {
37+ // The raw configuration data (owned string)
38+ let config_data = String :: from ( "127.0.0.1 9000" ) ;
39+
40+ // We parse it into our struct.
41+ // 'server' now borrows from 'config_data'.
42+ let server = ServerConfig :: parse ( & config_data) ;
43+
44+ println ! ( "Server Configuration:" ) ;
45+ println ! ( "Address: {}" , server. address) ;
46+ println ! ( "Port: {}" , server. port) ;
47+
48+ // If we dropped 'config_data' here, we could no longer use 'server'.
49+ // drop(config_data); // Uncommenting this would cause a compile error!
50+ }
0 commit comments