1 use anyhow::Context; 2 use protobuf::descriptor::DescriptorProto; 3 use protobuf::descriptor::EnumDescriptorProto; 4 use protobuf::descriptor::EnumValueDescriptorProto; 5 use protobuf::descriptor::FieldDescriptorProto; 6 use protobuf::descriptor::FileDescriptorProto; 7 use protobuf::descriptor::MethodDescriptorProto; 8 use protobuf::descriptor::OneofDescriptorProto; 9 use protobuf::descriptor::ServiceDescriptorProto; 10 use protobuf::reflect::FieldDescriptor; 11 use protobuf::reflect::FileDescriptor; 12 use protobuf::reflect::MessageDescriptor; 13 use protobuf::MessageFull; 14 use protobuf::UnknownFields; 15 use protobuf::UnknownValue; 16 use protobuf_support::lexer::str_lit::StrLitDecodeError; 17 18 use crate::model; 19 use crate::model::ProtobufConstant; 20 use crate::model::ProtobufConstantMessage; 21 use crate::model::ProtobufConstantMessageFieldName; 22 use crate::model::ProtobufOptionName; 23 use crate::model::ProtobufOptionNameExt; 24 use crate::model::ProtobufOptionNamePart; 25 use crate::model::WithLoc; 26 use crate::protobuf_path::ProtobufPath; 27 use crate::pure::convert::Resolver; 28 use crate::pure::convert::TypeResolved; 29 use crate::ProtobufAbsPath; 30 use crate::ProtobufAbsPathRef; 31 use crate::ProtobufIdent; 32 use crate::ProtobufIdentRef; 33 use crate::ProtobufRelPath; 34 use crate::ProtobufRelPathRef; 35 36 #[derive(Debug, thiserror::Error)] 37 enum OptionResolverError { 38 #[error(transparent)] 39 OtherError(anyhow::Error), 40 #[error("extension is not a message: {0}")] 41 ExtensionIsNotMessage(String), 42 #[error("unknown field name: {0}")] 43 UnknownFieldName(String), 44 #[error("wrong extension type: option {0} extendee {1} expected extendee {2}")] 45 WrongExtensionType(String, String, String), 46 #[error("extension not found: {0}")] 47 ExtensionNotFound(String), 48 #[error("unknown enum value: {0}")] 49 UnknownEnumValue(String), 50 #[error("unsupported extension type: {0} {1} {2}")] 51 UnsupportedExtensionType(String, String, model::ProtobufConstant), 52 #[error("builtin option {0} not found for options {1}")] 53 BuiltinOptionNotFound(String, String), 54 #[error("builtin option {0} points to a non-singular field of {1}")] 55 BuiltinOptionPointsToNonSingularField(String, String), 56 #[error("incorrect string literal: {0}")] 57 StrLitDecodeError(#[source] StrLitDecodeError), 58 #[error("wrong option type, expecting {0}, got `{1}`")] 59 WrongOptionType(&'static str, String), 60 #[error("Message field requires a message constant")] 61 MessageFieldRequiresMessageConstant, 62 #[error("message not found by name {0}")] 63 MessageNotFound(ProtobufAbsPath), 64 #[error("message not found by name {0}")] 65 MessageFoundMoreThanOnce(ProtobufAbsPath), 66 } 67 68 #[derive(Clone)] 69 enum LookupScope2 { 70 File(FileDescriptor), 71 Message(MessageDescriptor, ProtobufAbsPath), 72 } 73 74 impl LookupScope2 { current_path(&self) -> ProtobufAbsPath75 fn current_path(&self) -> ProtobufAbsPath { 76 match self { 77 LookupScope2::File(f) => ProtobufAbsPath::package_from_file_descriptor(f), 78 LookupScope2::Message(_, p) => p.clone(), 79 } 80 } 81 messages(&self) -> Vec<MessageDescriptor>82 fn messages(&self) -> Vec<MessageDescriptor> { 83 match self { 84 LookupScope2::File(file) => file.messages().collect(), 85 LookupScope2::Message(message, _) => message.nested_messages().collect(), 86 } 87 } 88 down(&self, name: &ProtobufIdentRef) -> Option<LookupScope2>89 fn down(&self, name: &ProtobufIdentRef) -> Option<LookupScope2> { 90 match self.messages().iter().find(|m| m.name() == name.as_str()) { 91 Some(m) => { 92 let mut path = self.current_path(); 93 path.push_simple(name.clone()); 94 Some(LookupScope2::Message(m.clone(), path)) 95 } 96 None => None, 97 } 98 } 99 extensions(&self) -> Vec<FieldDescriptor>100 fn extensions(&self) -> Vec<FieldDescriptor> { 101 match self { 102 LookupScope2::File(f) => f.extensions().collect(), 103 LookupScope2::Message(m, _) => m.extensions().collect(), 104 } 105 } 106 } 107 108 #[derive(Clone)] 109 pub(crate) struct LookupScopeUnion2 { 110 path: ProtobufAbsPath, 111 scopes: Vec<LookupScope2>, 112 partial_scopes: Vec<FileDescriptor>, 113 } 114 115 impl LookupScopeUnion2 { down(&self, name: &ProtobufIdentRef) -> LookupScopeUnion2116 fn down(&self, name: &ProtobufIdentRef) -> LookupScopeUnion2 { 117 let mut path: ProtobufAbsPath = self.path.clone(); 118 path.push_simple(name); 119 120 let mut scopes: Vec<_> = self.scopes.iter().flat_map(|f| f.down(name)).collect(); 121 let mut partial_scopes = Vec::new(); 122 123 for partial_scope in &self.partial_scopes { 124 let package = ProtobufAbsPath::package_from_file_descriptor(partial_scope); 125 if package.as_ref() == path.as_ref() { 126 scopes.push(LookupScope2::File(partial_scope.clone())); 127 } else if package.starts_with(&path) { 128 partial_scopes.push(partial_scope.clone()); 129 } 130 } 131 LookupScopeUnion2 { 132 path, 133 scopes, 134 partial_scopes, 135 } 136 } 137 lookup(&self, path: &ProtobufRelPath) -> LookupScopeUnion2138 fn lookup(&self, path: &ProtobufRelPath) -> LookupScopeUnion2 { 139 let mut scope = self.clone(); 140 for c in path.components() { 141 scope = scope.down(c); 142 } 143 scope 144 } 145 extensions(&self) -> Vec<FieldDescriptor>146 fn extensions(&self) -> Vec<FieldDescriptor> { 147 self.scopes.iter().flat_map(|s| s.extensions()).collect() 148 } 149 as_message(&self) -> anyhow::Result<MessageDescriptor>150 fn as_message(&self) -> anyhow::Result<MessageDescriptor> { 151 let mut messages: Vec<MessageDescriptor> = self 152 .scopes 153 .iter() 154 .filter_map(|s| match s { 155 LookupScope2::Message(m, _) => Some(m.clone()), 156 _ => None, 157 }) 158 .collect(); 159 let message = match messages.pop() { 160 Some(m) => m, 161 None => return Err(OptionResolverError::MessageNotFound(self.path.clone()).into()), 162 }; 163 if !messages.is_empty() { 164 return Err(OptionResolverError::MessageFoundMoreThanOnce(self.path.clone()).into()); 165 } 166 Ok(message) 167 } 168 } 169 170 pub(crate) trait ProtobufOptions { by_name(&self, name: &str) -> Option<&model::ProtobufConstant>171 fn by_name(&self, name: &str) -> Option<&model::ProtobufConstant>; 172 by_name_bool(&self, name: &str) -> anyhow::Result<Option<bool>>173 fn by_name_bool(&self, name: &str) -> anyhow::Result<Option<bool>> { 174 match self.by_name(name) { 175 Some(model::ProtobufConstant::Bool(b)) => Ok(Some(*b)), 176 Some(c) => Err(OptionResolverError::WrongOptionType("bool", c.to_string()).into()), 177 None => Ok(None), 178 } 179 } 180 by_name_string(&self, name: &str) -> anyhow::Result<Option<String>>181 fn by_name_string(&self, name: &str) -> anyhow::Result<Option<String>> { 182 match self.by_name(name) { 183 Some(model::ProtobufConstant::String(s)) => s 184 .decode_utf8() 185 .map(Some) 186 .map_err(|e| OptionResolverError::StrLitDecodeError(e).into()), 187 Some(c) => Err(OptionResolverError::WrongOptionType("string", c.to_string()).into()), 188 None => Ok(None), 189 } 190 } 191 } 192 193 impl<'a> ProtobufOptions for &'a [model::ProtobufOption] { by_name(&self, name: &str) -> Option<&model::ProtobufConstant>194 fn by_name(&self, name: &str) -> Option<&model::ProtobufConstant> { 195 let option_name = ProtobufOptionName::simple(name); 196 for model::ProtobufOption { name, value } in *self { 197 if name == &option_name { 198 return Some(&value); 199 } 200 } 201 None 202 } 203 } 204 205 pub(crate) struct OptionResoler<'a> { 206 pub(crate) resolver: &'a Resolver<'a>, 207 pub(crate) descriptor_without_options: FileDescriptor, 208 } 209 210 impl<'a> OptionResoler<'a> { all_files(&self) -> Vec<FileDescriptor>211 fn all_files(&self) -> Vec<FileDescriptor> { 212 let mut files = Vec::new(); 213 files.push(self.descriptor_without_options.clone()); 214 files.extend( 215 self.resolver 216 .type_resolver 217 .deps 218 .iter() 219 .map(|p| p.descriptor.clone()), 220 ); 221 files 222 } 223 root_scope(&self) -> LookupScopeUnion2224 fn root_scope(&self) -> LookupScopeUnion2 { 225 let (scopes, partial_scopes) = self 226 .all_files() 227 .into_iter() 228 .partition::<Vec<_>, _>(|f| ProtobufAbsPath::package_from_file_descriptor(f).is_root()); 229 LookupScopeUnion2 { 230 path: ProtobufAbsPath::root(), 231 scopes: scopes.into_iter().map(LookupScope2::File).collect(), 232 partial_scopes, 233 } 234 } 235 lookup(&self, path: &ProtobufAbsPath) -> LookupScopeUnion2236 fn lookup(&self, path: &ProtobufAbsPath) -> LookupScopeUnion2 { 237 self.root_scope().lookup(&path.to_root_rel()) 238 } 239 find_message_by_abs_name( &self, path: &ProtobufAbsPath, ) -> anyhow::Result<MessageDescriptor>240 fn find_message_by_abs_name( 241 &self, 242 path: &ProtobufAbsPath, 243 ) -> anyhow::Result<MessageDescriptor> { 244 let scope = self.lookup(path); 245 scope.as_message() 246 } 247 scope_resolved_candidates_rel( scope: &ProtobufAbsPathRef, rel: &ProtobufRelPathRef, ) -> Vec<ProtobufAbsPath>248 fn scope_resolved_candidates_rel( 249 scope: &ProtobufAbsPathRef, 250 rel: &ProtobufRelPathRef, 251 ) -> Vec<ProtobufAbsPath> { 252 scope 253 .self_and_parents() 254 .into_iter() 255 .map(|a| { 256 let mut a = a.to_owned(); 257 a.push_relative(rel); 258 a 259 }) 260 .collect() 261 } 262 scope_resolved_candidates( scope: &ProtobufAbsPathRef, path: &ProtobufPath, ) -> Vec<ProtobufAbsPath>263 fn scope_resolved_candidates( 264 scope: &ProtobufAbsPathRef, 265 path: &ProtobufPath, 266 ) -> Vec<ProtobufAbsPath> { 267 match path { 268 ProtobufPath::Abs(p) => vec![p.clone()], 269 ProtobufPath::Rel(p) => Self::scope_resolved_candidates_rel(scope, p), 270 } 271 } 272 find_extension_by_abs_path( &self, path: &ProtobufAbsPathRef, ) -> anyhow::Result<Option<FieldDescriptor>>273 fn find_extension_by_abs_path( 274 &self, 275 path: &ProtobufAbsPathRef, 276 ) -> anyhow::Result<Option<FieldDescriptor>> { 277 let mut path = path.to_owned(); 278 let extension = path.pop().unwrap(); 279 280 let scope = self.lookup(&path); 281 282 for ext in scope.extensions() { 283 if ext.name() == extension.get() { 284 return Ok(Some(ext.clone())); 285 } 286 } 287 288 Ok(None) 289 } 290 find_extension_by_path( &self, scope: &ProtobufAbsPathRef, path: &ProtobufPath, ) -> anyhow::Result<FieldDescriptor>291 fn find_extension_by_path( 292 &self, 293 scope: &ProtobufAbsPathRef, 294 path: &ProtobufPath, 295 ) -> anyhow::Result<FieldDescriptor> { 296 for candidate in Self::scope_resolved_candidates(scope, path) { 297 if let Some(e) = self.find_extension_by_abs_path(&candidate)? { 298 return Ok(e); 299 } 300 } 301 302 Err(OptionResolverError::ExtensionNotFound(path.to_string()).into()) 303 } 304 ext_resolve_field_ext( &self, scope: &ProtobufAbsPathRef, message: &MessageDescriptor, field_name: &ProtobufPath, ) -> anyhow::Result<FieldDescriptor>305 fn ext_resolve_field_ext( 306 &self, 307 scope: &ProtobufAbsPathRef, 308 message: &MessageDescriptor, 309 field_name: &ProtobufPath, 310 ) -> anyhow::Result<FieldDescriptor> { 311 let expected_extendee = ProtobufAbsPath::from_message(message); 312 let field = self.find_extension_by_path(scope, field_name)?; 313 if ProtobufAbsPath::new(field.proto().extendee()) != expected_extendee { 314 return Err(OptionResolverError::WrongExtensionType( 315 format!("{}", field_name), 316 format!("{}", field.proto().extendee()), 317 format!("{}", expected_extendee), 318 ) 319 .into()); 320 } 321 322 Ok(field) 323 } 324 ext_resolve_field( &self, scope: &ProtobufAbsPathRef, message: &MessageDescriptor, field: &ProtobufOptionNamePart, ) -> anyhow::Result<FieldDescriptor>325 fn ext_resolve_field( 326 &self, 327 scope: &ProtobufAbsPathRef, 328 message: &MessageDescriptor, 329 field: &ProtobufOptionNamePart, 330 ) -> anyhow::Result<FieldDescriptor> { 331 match field { 332 ProtobufOptionNamePart::Direct(field) => match message.field_by_name(field.get()) { 333 Some(field) => Ok(field), 334 None => Err(OptionResolverError::UnknownFieldName(field.to_string()).into()), 335 }, 336 ProtobufOptionNamePart::Ext(field) => { 337 Ok(self.ext_resolve_field_ext(scope, message, field)?) 338 } 339 } 340 } 341 custom_option_ext_step( &self, scope: &ProtobufAbsPathRef, options_type: &MessageDescriptor, options: &mut UnknownFields, option_name: &ProtobufOptionNamePart, option_name_rem: &[ProtobufOptionNamePart], option_value: &ProtobufConstant, ) -> anyhow::Result<()>342 fn custom_option_ext_step( 343 &self, 344 scope: &ProtobufAbsPathRef, 345 options_type: &MessageDescriptor, 346 options: &mut UnknownFields, 347 option_name: &ProtobufOptionNamePart, 348 option_name_rem: &[ProtobufOptionNamePart], 349 option_value: &ProtobufConstant, 350 ) -> anyhow::Result<()> { 351 let field = self.ext_resolve_field(scope, options_type, option_name)?; 352 353 let field_type = TypeResolved::from_field(field.proto()); 354 355 match option_name_rem.split_first() { 356 Some((first, rem)) => { 357 match field_type { 358 TypeResolved::Message(message_name) => { 359 let m = self.find_message_by_abs_name(&message_name)?; 360 let mut unknown_fields = UnknownFields::new(); 361 self.custom_option_ext_step( 362 scope, 363 &m, 364 &mut unknown_fields, 365 first, 366 rem, 367 option_value, 368 )?; 369 options.add_length_delimited( 370 field.proto().number() as u32, 371 unknown_fields.write_to_bytes(), 372 ); 373 Ok(()) 374 } 375 TypeResolved::Group(..) => { 376 // TODO: implement 377 Ok(()) 378 } 379 _ => Err(OptionResolverError::ExtensionIsNotMessage(format!( 380 "scope: {}, option name: {}", 381 scope, option_name 382 )) 383 .into()), 384 } 385 } 386 None => { 387 let value = match self.option_value_to_unknown_value( 388 &field_type, 389 option_value, 390 &format!("{}", option_name), 391 ) { 392 Ok(value) => value, 393 Err(e) => { 394 let e = e.context(format!( 395 "parsing custom option `{}` value `{}` at `{}`", 396 option_name, option_value, scope 397 )); 398 return Err(e.into()); 399 } 400 }; 401 402 options.add_value(field.proto().number() as u32, value); 403 Ok(()) 404 } 405 } 406 } 407 custom_option_ext<M>( &self, scope: &ProtobufAbsPathRef, options: &mut M, option_name: &ProtobufOptionNameExt, option_value: &ProtobufConstant, ) -> anyhow::Result<()> where M: MessageFull,408 fn custom_option_ext<M>( 409 &self, 410 scope: &ProtobufAbsPathRef, 411 options: &mut M, 412 option_name: &ProtobufOptionNameExt, 413 option_value: &ProtobufConstant, 414 ) -> anyhow::Result<()> 415 where 416 M: MessageFull, 417 { 418 self.custom_option_ext_step( 419 scope, 420 &M::descriptor(), 421 options.mut_unknown_fields(), 422 &option_name.0[0], 423 &option_name.0[1..], 424 option_value, 425 ) 426 } 427 fixed32( v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>428 fn fixed32( 429 v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>, 430 ) -> anyhow::Result<UnknownValue> { 431 Ok(UnknownValue::Fixed32(v.try_into()?)) 432 } 433 sfixed32( v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>434 fn sfixed32( 435 v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, 436 ) -> anyhow::Result<UnknownValue> { 437 Ok(UnknownValue::sfixed32(v.try_into()?)) 438 } 439 fixed64( v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>440 fn fixed64( 441 v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>, 442 ) -> anyhow::Result<UnknownValue> { 443 Ok(UnknownValue::Fixed64(v.try_into()?)) 444 } 445 sfixed64( v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>446 fn sfixed64( 447 v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, 448 ) -> anyhow::Result<UnknownValue> { 449 Ok(UnknownValue::sfixed64(v.try_into()?)) 450 } 451 int32( v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>452 fn int32( 453 v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, 454 ) -> anyhow::Result<UnknownValue> { 455 Ok(UnknownValue::int32(v.try_into()?)) 456 } 457 int64( v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>458 fn int64( 459 v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, 460 ) -> anyhow::Result<UnknownValue> { 461 Ok(UnknownValue::int64(v.try_into()?)) 462 } 463 uint32( v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>464 fn uint32( 465 v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>, 466 ) -> anyhow::Result<UnknownValue> { 467 Ok(UnknownValue::Varint(v.try_into()? as u64)) 468 } 469 uint64( v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>470 fn uint64( 471 v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>, 472 ) -> anyhow::Result<UnknownValue> { 473 Ok(UnknownValue::Varint(v.try_into()?)) 474 } 475 sint32( v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>476 fn sint32( 477 v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, 478 ) -> anyhow::Result<UnknownValue> { 479 Ok(UnknownValue::sint32(v.try_into()?)) 480 } 481 sint64( v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>482 fn sint64( 483 v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, 484 ) -> anyhow::Result<UnknownValue> { 485 Ok(UnknownValue::sint64(v.try_into()?)) 486 } 487 option_value_message_to_unknown_value( &self, field_type: &TypeResolved, value: &ProtobufConstantMessage, option_name_for_diag: &str, ) -> anyhow::Result<UnknownValue>488 fn option_value_message_to_unknown_value( 489 &self, 490 field_type: &TypeResolved, 491 value: &ProtobufConstantMessage, 492 option_name_for_diag: &str, 493 ) -> anyhow::Result<UnknownValue> { 494 match &field_type { 495 TypeResolved::Message(ma) => { 496 let m = self 497 .resolver 498 .find_message_by_abs_name(ma) 499 .map_err(OptionResolverError::OtherError)? 500 .t; 501 let mut unknown_fields = UnknownFields::new(); 502 for (n, v) in &value.fields { 503 match n { 504 ProtobufConstantMessageFieldName::Regular(n) => { 505 let f = match m.field_by_name(n.as_str()) { 506 Some(f) => f, 507 None => { 508 return Err( 509 OptionResolverError::UnknownFieldName(n.clone()).into() 510 ) 511 } 512 }; 513 let u = self 514 .option_value_field_to_unknown_value( 515 ma, 516 v, 517 n, 518 &f.typ, 519 option_name_for_diag, 520 ) 521 .map_err(OptionResolverError::OtherError)?; 522 unknown_fields.add_value(f.number as u32, u); 523 } 524 ProtobufConstantMessageFieldName::Extension(..) => { 525 // TODO: implement extension fields in constants 526 } 527 ProtobufConstantMessageFieldName::AnyTypeUrl(..) => { 528 // TODO: implement any type url in constants 529 } 530 } 531 } 532 Ok(UnknownValue::LengthDelimited( 533 unknown_fields.write_to_bytes(), 534 )) 535 } 536 _ => Err(OptionResolverError::MessageFieldRequiresMessageConstant.into()), 537 } 538 } 539 option_value_to_unknown_value( &self, field_type: &TypeResolved, value: &model::ProtobufConstant, option_name_for_diag: &str, ) -> anyhow::Result<UnknownValue>540 fn option_value_to_unknown_value( 541 &self, 542 field_type: &TypeResolved, 543 value: &model::ProtobufConstant, 544 option_name_for_diag: &str, 545 ) -> anyhow::Result<UnknownValue> { 546 match value { 547 &model::ProtobufConstant::Bool(b) => { 548 if field_type != &TypeResolved::Bool { 549 {} 550 } else { 551 return Ok(UnknownValue::Varint(if b { 1 } else { 0 })); 552 } 553 } 554 &model::ProtobufConstant::U64(v) => match field_type { 555 TypeResolved::Fixed64 => return Self::fixed64(v), 556 TypeResolved::Sfixed64 => return Self::sfixed64(v), 557 TypeResolved::Fixed32 => return Self::fixed32(v), 558 TypeResolved::Sfixed32 => return Self::sfixed32(v), 559 TypeResolved::Int32 => return Self::int32(v), 560 TypeResolved::Int64 => return Self::int64(v), 561 TypeResolved::Uint64 => return Self::uint64(v), 562 TypeResolved::Uint32 => return Self::uint32(v), 563 TypeResolved::Sint64 => return Self::sint64(v), 564 TypeResolved::Sint32 => return Self::sint32(v), 565 TypeResolved::Float => return Ok(UnknownValue::float(v as f32)), 566 TypeResolved::Double => return Ok(UnknownValue::double(v as f64)), 567 _ => {} 568 }, 569 &model::ProtobufConstant::I64(v) => match field_type { 570 TypeResolved::Fixed64 => return Self::fixed64(v), 571 TypeResolved::Sfixed64 => return Self::sfixed64(v), 572 TypeResolved::Fixed32 => return Self::fixed32(v), 573 TypeResolved::Sfixed32 => return Self::sfixed32(v), 574 TypeResolved::Int64 => return Self::int64(v), 575 TypeResolved::Int32 => return Self::int32(v), 576 TypeResolved::Uint64 => return Self::uint64(v), 577 TypeResolved::Uint32 => return Self::uint32(v), 578 TypeResolved::Sint64 => return Self::sint64(v), 579 TypeResolved::Sint32 => return Self::sint32(v), 580 TypeResolved::Float => return Ok(UnknownValue::float(v as f32)), 581 TypeResolved::Double => return Ok(UnknownValue::double(v as f64)), 582 _ => {} 583 }, 584 &model::ProtobufConstant::F64(f) => match field_type { 585 TypeResolved::Float => return Ok(UnknownValue::float(f as f32)), 586 TypeResolved::Double => return Ok(UnknownValue::double(f)), 587 TypeResolved::Fixed32 => return Ok(UnknownValue::Fixed32(f as u32)), 588 TypeResolved::Fixed64 => return Ok(UnknownValue::Fixed64(f as u64)), 589 TypeResolved::Sfixed32 => return Ok(UnknownValue::sfixed32(f as i32)), 590 TypeResolved::Sfixed64 => return Ok(UnknownValue::sfixed64(f as i64)), 591 TypeResolved::Int32 | TypeResolved::Int64 => { 592 return Ok(UnknownValue::int64(f as i64)) 593 } 594 TypeResolved::Uint32 | TypeResolved::Uint64 => { 595 return Ok(UnknownValue::Varint(f as u64)) 596 } 597 TypeResolved::Sint64 => return Ok(UnknownValue::sint64(f as i64)), 598 TypeResolved::Sint32 => return Ok(UnknownValue::sint32(f as i32)), 599 _ => {} 600 }, 601 &model::ProtobufConstant::String(ref s) => match field_type { 602 TypeResolved::String => { 603 return Ok(UnknownValue::LengthDelimited(s.decode_utf8()?.into_bytes())) 604 } 605 TypeResolved::Bytes => return Ok(UnknownValue::LengthDelimited(s.decode_bytes()?)), 606 _ => {} 607 }, 608 model::ProtobufConstant::Ident(ident) => match &field_type { 609 TypeResolved::Enum(e) => { 610 let e = self 611 .resolver 612 .find_enum_by_abs_name(e) 613 .map_err(OptionResolverError::OtherError)?; 614 let n = match e 615 .values 616 .iter() 617 .find(|v| v.name == format!("{}", ident)) 618 .map(|v| v.number) 619 { 620 Some(n) => n, 621 None => { 622 return Err( 623 OptionResolverError::UnknownEnumValue(ident.to_string()).into() 624 ) 625 } 626 }; 627 return Ok(UnknownValue::int32(n)); 628 } 629 _ => {} 630 }, 631 model::ProtobufConstant::Message(mo) => { 632 return self.option_value_message_to_unknown_value( 633 &field_type, 634 mo, 635 option_name_for_diag, 636 ); 637 } 638 }; 639 640 Err(match field_type { 641 _ => OptionResolverError::UnsupportedExtensionType( 642 option_name_for_diag.to_owned(), 643 format!("{:?}", field_type), 644 value.clone(), 645 ) 646 .into(), 647 }) 648 } 649 option_value_field_to_unknown_value( &self, scope: &ProtobufAbsPath, value: &model::ProtobufConstant, name: &str, field_type: &model::FieldType, option_name_for_diag: &str, ) -> anyhow::Result<UnknownValue>650 fn option_value_field_to_unknown_value( 651 &self, 652 scope: &ProtobufAbsPath, 653 value: &model::ProtobufConstant, 654 name: &str, 655 field_type: &model::FieldType, 656 option_name_for_diag: &str, 657 ) -> anyhow::Result<UnknownValue> { 658 let field_type = self.resolver.field_type(&scope, name, field_type)?; 659 Ok(self 660 .option_value_to_unknown_value(&field_type, value, option_name_for_diag) 661 .context("parsing custom option value")?) 662 } 663 custom_option_builtin<M>( &self, _scope: &ProtobufAbsPathRef, options: &mut M, option: &ProtobufIdent, option_value: &ProtobufConstant, ) -> anyhow::Result<()> where M: MessageFull,664 fn custom_option_builtin<M>( 665 &self, 666 _scope: &ProtobufAbsPathRef, 667 options: &mut M, 668 option: &ProtobufIdent, 669 option_value: &ProtobufConstant, 670 ) -> anyhow::Result<()> 671 where 672 M: MessageFull, 673 { 674 if M::descriptor().full_name() == "google.protobuf.FieldOptions" { 675 if option.get() == "default" || option.get() == "json_name" { 676 // some options are written to non-options message and handled outside 677 return Ok(()); 678 } 679 } 680 match M::descriptor().field_by_name(option.get()) { 681 Some(field) => { 682 if field.is_repeated_or_map() { 683 return Err(OptionResolverError::BuiltinOptionPointsToNonSingularField( 684 M::descriptor().full_name().to_owned(), 685 option.get().to_owned(), 686 ) 687 .into()); 688 } 689 690 field.set_singular_field( 691 options, 692 option_value.as_type(field.singular_runtime_type())?, 693 ); 694 return Ok(()); 695 } 696 None => { 697 return Err(OptionResolverError::BuiltinOptionNotFound( 698 M::descriptor().full_name().to_owned(), 699 option.get().to_owned(), 700 ) 701 .into()) 702 } 703 } 704 } 705 custom_option<M>( &self, scope: &ProtobufAbsPathRef, options: &mut M, option: &model::ProtobufOption, ) -> anyhow::Result<()> where M: MessageFull,706 fn custom_option<M>( 707 &self, 708 scope: &ProtobufAbsPathRef, 709 options: &mut M, 710 option: &model::ProtobufOption, 711 ) -> anyhow::Result<()> 712 where 713 M: MessageFull, 714 { 715 match &option.name { 716 ProtobufOptionName::Builtin(simple) => { 717 self.custom_option_builtin(scope, options, simple, &option.value) 718 } 719 ProtobufOptionName::Ext(e) => self.custom_option_ext(scope, options, e, &option.value), 720 } 721 } 722 custom_options<M>( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<M>> where M: MessageFull,723 fn custom_options<M>( 724 &self, 725 scope: &ProtobufAbsPathRef, 726 input: &[model::ProtobufOption], 727 ) -> anyhow::Result<Option<M>> 728 where 729 M: MessageFull, 730 { 731 if input.is_empty() { 732 // Empty options do not have to represented to unset message field, 733 // but this is what Google's parser does. 734 return Ok(None); 735 } 736 737 let mut options = M::new(); 738 739 for option in input { 740 self.custom_option(scope, &mut options, option)?; 741 } 742 Ok(Some(options)) 743 } 744 file_options( &self, scope: &ProtobufAbsPath, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::FileOptions>>745 fn file_options( 746 &self, 747 scope: &ProtobufAbsPath, 748 input: &[model::ProtobufOption], 749 ) -> anyhow::Result<Option<protobuf::descriptor::FileOptions>> { 750 self.custom_options(scope, input) 751 } 752 enum_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::EnumOptions>>753 fn enum_options( 754 &self, 755 scope: &ProtobufAbsPathRef, 756 input: &[model::ProtobufOption], 757 ) -> anyhow::Result<Option<protobuf::descriptor::EnumOptions>> { 758 self.custom_options(scope, input) 759 } 760 enum_value_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::EnumValueOptions>>761 fn enum_value_options( 762 &self, 763 scope: &ProtobufAbsPathRef, 764 input: &[model::ProtobufOption], 765 ) -> anyhow::Result<Option<protobuf::descriptor::EnumValueOptions>> { 766 self.custom_options(scope, input) 767 } 768 field_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::FieldOptions>>769 fn field_options( 770 &self, 771 scope: &ProtobufAbsPathRef, 772 input: &[model::ProtobufOption], 773 ) -> anyhow::Result<Option<protobuf::descriptor::FieldOptions>> { 774 self.custom_options(scope, input) 775 } 776 message_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::MessageOptions>>777 fn message_options( 778 &self, 779 scope: &ProtobufAbsPathRef, 780 input: &[model::ProtobufOption], 781 ) -> anyhow::Result<Option<protobuf::descriptor::MessageOptions>> { 782 self.custom_options(scope, input) 783 } 784 oneof_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::OneofOptions>>785 fn oneof_options( 786 &self, 787 scope: &ProtobufAbsPathRef, 788 input: &[model::ProtobufOption], 789 ) -> anyhow::Result<Option<protobuf::descriptor::OneofOptions>> { 790 self.custom_options(scope, input) 791 } 792 method( &self, method_proto: &mut MethodDescriptorProto, method_model: &model::Method, ) -> anyhow::Result<()>793 fn method( 794 &self, 795 method_proto: &mut MethodDescriptorProto, 796 method_model: &model::Method, 797 ) -> anyhow::Result<()> { 798 method_proto.options = self.service_method_options(&method_model.options)?.into(); 799 Ok(()) 800 } 801 service_options( &self, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::ServiceOptions>>802 fn service_options( 803 &self, 804 input: &[model::ProtobufOption], 805 ) -> anyhow::Result<Option<protobuf::descriptor::ServiceOptions>> { 806 self.custom_options(&self.resolver.current_file.package, input) 807 } 808 service_method_options( &self, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::MethodOptions>>809 fn service_method_options( 810 &self, 811 input: &[model::ProtobufOption], 812 ) -> anyhow::Result<Option<protobuf::descriptor::MethodOptions>> { 813 self.custom_options(&self.resolver.current_file.package, input) 814 } 815 service( &self, service_proto: &mut ServiceDescriptorProto, service_model: &WithLoc<model::Service>, ) -> anyhow::Result<()>816 fn service( 817 &self, 818 service_proto: &mut ServiceDescriptorProto, 819 service_model: &WithLoc<model::Service>, 820 ) -> anyhow::Result<()> { 821 service_proto.options = self.service_options(&service_model.options)?.into(); 822 823 for service_method_model in &service_model.methods { 824 let mut method_proto = service_proto 825 .method 826 .iter_mut() 827 .find(|method| method.name() == service_method_model.name) 828 .unwrap(); 829 self.method(&mut method_proto, service_method_model)?; 830 } 831 832 Ok(()) 833 } 834 enum_value( &self, scope: &ProtobufAbsPathRef, enum_value_proto: &mut EnumValueDescriptorProto, enum_value_model: &model::EnumValue, ) -> anyhow::Result<()>835 fn enum_value( 836 &self, 837 scope: &ProtobufAbsPathRef, 838 enum_value_proto: &mut EnumValueDescriptorProto, 839 enum_value_model: &model::EnumValue, 840 ) -> anyhow::Result<()> { 841 enum_value_proto.options = self 842 .enum_value_options(scope, &enum_value_model.options)? 843 .into(); 844 Ok(()) 845 } 846 enumeration( &self, scope: &ProtobufAbsPathRef, enum_proto: &mut EnumDescriptorProto, enum_model: &WithLoc<model::Enumeration>, ) -> anyhow::Result<()>847 fn enumeration( 848 &self, 849 scope: &ProtobufAbsPathRef, 850 enum_proto: &mut EnumDescriptorProto, 851 enum_model: &WithLoc<model::Enumeration>, 852 ) -> anyhow::Result<()> { 853 enum_proto.options = self.enum_options(scope, &enum_model.options)?.into(); 854 855 for enum_value_model in &enum_model.values { 856 let mut enum_value_proto = enum_proto 857 .value 858 .iter_mut() 859 .find(|v| v.name() == enum_value_model.name) 860 .unwrap(); 861 self.enum_value(scope, &mut enum_value_proto, enum_value_model)?; 862 } 863 864 Ok(()) 865 } 866 oneof( &self, scope: &ProtobufAbsPathRef, oneof_proto: &mut OneofDescriptorProto, oneof_model: &model::OneOf, ) -> anyhow::Result<()>867 fn oneof( 868 &self, 869 scope: &ProtobufAbsPathRef, 870 oneof_proto: &mut OneofDescriptorProto, 871 oneof_model: &model::OneOf, 872 ) -> anyhow::Result<()> { 873 oneof_proto.options = self.oneof_options(scope, &oneof_model.options)?.into(); 874 Ok(()) 875 } 876 field( &self, scope: &ProtobufAbsPathRef, field_proto: &mut FieldDescriptorProto, field_model: &model::Field, ) -> anyhow::Result<()>877 fn field( 878 &self, 879 scope: &ProtobufAbsPathRef, 880 field_proto: &mut FieldDescriptorProto, 881 field_model: &model::Field, 882 ) -> anyhow::Result<()> { 883 field_proto.options = self.field_options(scope, &field_model.options)?.into(); 884 Ok(()) 885 } 886 message( &self, scope: &ProtobufAbsPathRef, message_proto: &mut DescriptorProto, message_model: &WithLoc<model::Message>, ) -> anyhow::Result<()>887 fn message( 888 &self, 889 scope: &ProtobufAbsPathRef, 890 message_proto: &mut DescriptorProto, 891 message_model: &WithLoc<model::Message>, 892 ) -> anyhow::Result<()> { 893 message_proto.options = self.message_options(scope, &message_model.options)?.into(); 894 895 let mut nested_scope = scope.to_owned(); 896 nested_scope.push_simple(ProtobufIdentRef::new(&message_proto.name())); 897 898 for field_model in &message_model.regular_fields_including_in_oneofs() { 899 let mut field_proto = message_proto 900 .field 901 .iter_mut() 902 .find(|field| field.name() == field_model.name) 903 .unwrap(); 904 self.field(&nested_scope, &mut field_proto, field_model)?; 905 } 906 for field_model in &message_model.extensions { 907 let field_proto = message_proto 908 .extension 909 .iter_mut() 910 .find(|field| field.name() == field_model.field.name) 911 .unwrap(); 912 self.field(&nested_scope, field_proto, &field_model.field)?; 913 } 914 915 for nested_message_model in &message_model.messages { 916 let nested_message_proto = message_proto 917 .nested_type 918 .iter_mut() 919 .find(|nested_message_proto| { 920 nested_message_proto.name() == nested_message_model.name 921 }) 922 .unwrap(); 923 self.message(&nested_scope, nested_message_proto, nested_message_model)?; 924 } 925 926 for nested_enum_model in &message_model.enums { 927 let nested_enum_proto = message_proto 928 .enum_type 929 .iter_mut() 930 .find(|nested_enum_proto| nested_enum_proto.name() == nested_enum_model.name) 931 .unwrap(); 932 self.enumeration(&nested_scope, nested_enum_proto, nested_enum_model)?; 933 } 934 935 for oneof_model in &message_model.oneofs() { 936 let oneof_proto = message_proto 937 .oneof_decl 938 .iter_mut() 939 .find(|oneof_proto| oneof_proto.name() == oneof_model.name) 940 .unwrap(); 941 self.oneof(&nested_scope, oneof_proto, oneof_model)?; 942 } 943 944 Ok(()) 945 } 946 file(&self, output: &mut FileDescriptorProto) -> anyhow::Result<()>947 pub(crate) fn file(&self, output: &mut FileDescriptorProto) -> anyhow::Result<()> { 948 // TODO: use it to resolve messages. 949 let _ = &self.descriptor_without_options; 950 951 for message_model in &self.resolver.current_file.messages { 952 let message_proto = output 953 .message_type 954 .iter_mut() 955 .find(|m| m.name() == message_model.name) 956 .unwrap(); 957 self.message( 958 &self.resolver.current_file.package, 959 message_proto, 960 message_model, 961 )?; 962 } 963 964 for enum_model in &self.resolver.current_file.enums { 965 let enum_proto = output 966 .enum_type 967 .iter_mut() 968 .find(|e| e.name() == enum_model.name) 969 .unwrap(); 970 self.enumeration(&self.resolver.current_file.package, enum_proto, enum_model)?; 971 } 972 973 for service_proto in &mut output.service { 974 let service_model = self 975 .resolver 976 .current_file 977 .services 978 .iter() 979 .find(|s| s.name == service_proto.name()) 980 .unwrap(); 981 self.service(service_proto, service_model)?; 982 } 983 984 for extension_model in &self.resolver.current_file.extensions { 985 let extension_proto = output 986 .extension 987 .iter_mut() 988 .find(|e| e.name() == extension_model.field.name) 989 .unwrap(); 990 self.field( 991 &self.resolver.current_file.package, 992 extension_proto, 993 &extension_model.field, 994 )?; 995 } 996 997 output.options = self 998 .file_options( 999 &self.resolver.current_file.package, 1000 &self.resolver.current_file.options, 1001 )? 1002 .into(); 1003 1004 Ok(()) 1005 } 1006 } 1007