_field_values.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. # Copyright (c) 2025-2026 Buf Technologies, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from __future__ import annotations
  15. from math import copysign
  16. from typing import Any
  17. from ._descriptors import (
  18. DescField,
  19. DescFieldValue,
  20. DescFieldValueEnum,
  21. DescFieldValueList,
  22. DescFieldValueMap,
  23. DescFieldValueMessage,
  24. DescFieldValueScalar,
  25. DescFieldValueSingular,
  26. DescOneof,
  27. ScalarType,
  28. SupportedFieldPresence,
  29. )
  30. from ._typing import assert_never
  31. def scalar_zero_value(scalar_type: ScalarType) -> Any: # noqa: RET503
  32. """Return the zero value for a scalar type."""
  33. match scalar_type:
  34. case ScalarType.BOOL:
  35. return False
  36. case (
  37. ScalarType.INT32
  38. | ScalarType.INT64
  39. | ScalarType.UINT32
  40. | ScalarType.UINT64
  41. | ScalarType.SINT32
  42. | ScalarType.SINT64
  43. | ScalarType.FIXED32
  44. | ScalarType.FIXED64
  45. | ScalarType.SFIXED32
  46. | ScalarType.SFIXED64
  47. ):
  48. return 0
  49. case ScalarType.FLOAT | ScalarType.DOUBLE:
  50. return 0.0
  51. case ScalarType.STRING:
  52. return ""
  53. case ScalarType.BYTES:
  54. return b""
  55. case _:
  56. assert_never(scalar_type)
  57. def requires_presence(member: DescField) -> bool:
  58. """Returns whether this field needs separate presence tracking.
  59. Scalar and enum fields with explicit presence need separate
  60. tracking because their zero value (0, "", False, etc.) is a
  61. valid user-provided value, indistinguishable from "not set".
  62. Other field types carry presence in the value itself.
  63. """
  64. if (
  65. isinstance(member.value, DescFieldValueSingular)
  66. and member.value.oneof is None
  67. and not isinstance(member.value, DescFieldValueMessage)
  68. ):
  69. return member.presence != SupportedFieldPresence.IMPLICIT
  70. return False
  71. def default_value(member: DescFieldValue | DescOneof) -> Any: # noqa: RET503
  72. """Return the default value for the given field or oneof."""
  73. match member:
  74. case DescOneof() | DescFieldValueMessage():
  75. return None
  76. case DescFieldValueEnum(default_value=default):
  77. return member.enum.type(
  78. member.enum.values[0].number if default is None else default
  79. )
  80. case DescFieldValueScalar(default_value=default):
  81. if default is not None:
  82. return default
  83. return scalar_zero_value(member.scalar)
  84. case DescFieldValueList():
  85. return []
  86. case DescFieldValueMap():
  87. return {}
  88. case _:
  89. assert_never(member)
  90. def is_zero_value(member: DescFieldValue | DescOneof, value: Any) -> bool:
  91. """Returns whether the given field or oneof value is a zero value.
  92. Only used for fields with implicit presence.
  93. """
  94. if isinstance(member, DescFieldValueEnum):
  95. return value == member.enum.values[0].number
  96. if isinstance(member, DescFieldValueScalar) and member.scalar == ScalarType.FLOAT:
  97. return value == 0.0 and copysign(1, value) == 1
  98. return not bool(value)