[ObjC] Mark classes that shouldn't be subclassed as such.

Several of the classes vended by the runtime don't really support subclassing,
so mark them as such to get compiler enforcement just in case.

PiperOrigin-RevId: 505221732
pull/11697/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 55d21239e9
commit a185a6ea8a
  1. 10
      objectivec/GPBArray.h
  2. 1
      objectivec/GPBCodedInputStream.h
  3. 1
      objectivec/GPBCodedOutputStream.h
  4. 10
      objectivec/GPBDescriptor.h
  5. 55
      objectivec/GPBDictionary.h
  6. 3
      objectivec/GPBExtensionRegistry.h
  7. 3
      objectivec/GPBUnknownField.h
  8. 3
      objectivec/GPBUnknownFieldSet.h

@ -48,6 +48,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32Array : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -222,6 +223,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32Array : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -396,6 +398,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64Array : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -570,6 +573,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64Array : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -744,6 +748,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBFloatArray : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -918,6 +923,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBDoubleArray : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -1092,6 +1098,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolArray : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -1266,6 +1273,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBEnumArray : NSObject <NSCopying>
/** The number of elements contained in the array. */
@ -1583,6 +1591,7 @@ NS_ASSUME_NONNULL_END
//% *
//% * @note This class is not meant to be subclassed.
//% **/
//%__attribute__((objc_subclassing_restricted))
//%@interface GPB##NAME##Array : NSObject <NSCopying>
//%
//%/** The number of elements contained in the array. */
@ -1675,6 +1684,7 @@ NS_ASSUME_NONNULL_END
//% *
//% * @note This class is not meant to be subclassed.
//% **/
//%__attribute__((objc_subclassing_restricted))
//%@interface GPB##NAME##Array : NSObject <NSCopying>
//%
//%/** The number of elements contained in the array. */

@ -83,6 +83,7 @@ CF_EXTERN_C_END
*
* @note Subclassing of @c GPBCodedInputStream is NOT supported.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBCodedInputStream : NSObject
/**

@ -63,6 +63,7 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed;
*
* @note Subclassing of GPBCodedOutputStream is NOT supported.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBCodedOutputStream : NSObject
/**

@ -62,7 +62,8 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/**
* Describes a proto message.
**/
@interface GPBDescriptor : NSObject <NSCopying>
__attribute__((objc_subclassing_restricted))
@interface GPBDescriptor : NSObject<NSCopying>
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@ -124,6 +125,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/**
* Describes a proto file.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBFileDescriptor : NSObject
- (instancetype)init NS_UNAVAILABLE;
@ -149,6 +151,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/**
* Describes a oneof field.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBOneofDescriptor : NSObject
- (instancetype)init NS_UNAVAILABLE;
@ -182,6 +185,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/**
* Describes a proto field.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBFieldDescriptor : NSObject
- (instancetype)init NS_UNAVAILABLE;
@ -234,6 +238,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/**
* Describes a proto enum.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBEnumDescriptor : NSObject
- (instancetype)init NS_UNAVAILABLE;
@ -329,7 +334,8 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/**
* Describes a proto extension.
**/
@interface GPBExtensionDescriptor : NSObject <NSCopying>
__attribute__((objc_subclassing_restricted))
@interface GPBExtensionDescriptor : NSObject<NSCopying>
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

@ -57,6 +57,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32UInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -152,6 +153,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32Int32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -247,6 +249,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32UInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -342,6 +345,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32Int64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -437,6 +441,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32BoolDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -532,6 +537,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32FloatDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -627,6 +633,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32DoubleDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -722,6 +729,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32EnumDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -884,6 +892,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -978,6 +987,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32UInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1073,6 +1083,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32Int32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1168,6 +1179,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32UInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1263,6 +1275,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32Int64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1358,6 +1371,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32BoolDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1453,6 +1467,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32FloatDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1548,6 +1563,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32DoubleDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1643,6 +1659,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32EnumDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1805,6 +1822,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1899,6 +1917,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64UInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -1994,6 +2013,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64Int32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2089,6 +2109,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64UInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2184,6 +2205,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64Int64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2279,6 +2301,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64BoolDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2374,6 +2397,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64FloatDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2469,6 +2493,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64DoubleDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2564,6 +2589,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64EnumDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2726,6 +2752,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2820,6 +2847,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64UInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -2915,6 +2943,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64Int32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3010,6 +3039,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64UInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3105,6 +3135,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64Int64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3200,6 +3231,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64BoolDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3295,6 +3327,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64FloatDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3390,6 +3423,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64DoubleDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3485,6 +3519,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64EnumDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3647,6 +3682,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3741,6 +3777,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolUInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3836,6 +3873,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -3931,6 +3969,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolUInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4026,6 +4065,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4121,6 +4161,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolBoolDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4216,6 +4257,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolFloatDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4311,6 +4353,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolDoubleDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4406,6 +4449,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolEnumDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4568,6 +4612,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBBoolObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4662,6 +4707,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringUInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4757,6 +4803,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringInt32Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4852,6 +4899,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringUInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -4947,6 +4995,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringInt64Dictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -5042,6 +5091,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringBoolDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -5137,6 +5187,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringFloatDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -5232,6 +5283,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringDoubleDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -5327,6 +5379,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @note This class is not meant to be subclassed.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBStringEnumDictionary : NSObject <NSCopying>
/** Number of entries stored in this dictionary. */
@ -5550,6 +5603,7 @@ NS_ASSUME_NONNULL_END
//% *
//% * @note This class is not meant to be subclassed.
//% **/
//%__attribute__((objc_subclassing_restricted))
//%@interface DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) : NSObject <NSCopying>
//%
//%/** Number of entries stored in this dictionary. */
@ -5612,6 +5666,7 @@ NS_ASSUME_NONNULL_END
//% *
//% * @note This class is not meant to be subclassed.
//% **/
//%__attribute__((objc_subclassing_restricted))
//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject <NSCopying>
//%
//%/** Number of entries stored in this dictionary. */

@ -72,7 +72,8 @@ NS_ASSUME_NONNULL_BEGIN
* MyMessage *msg = [MyMessage parseData:data extensionRegistry:registry error:&parseError];
* ```
**/
@interface GPBExtensionRegistry : NSObject <NSCopying, GPBExtensionRegistry>
__attribute__((objc_subclassing_restricted))
@interface GPBExtensionRegistry : NSObject<NSCopying, GPBExtensionRegistry>
/**
* Adds the given GPBExtensionDescriptor to this registry.

@ -40,7 +40,8 @@ NS_ASSUME_NONNULL_BEGIN
* Store an unknown field. These are used in conjunction with
* GPBUnknownFieldSet.
**/
@interface GPBUnknownField : NSObject <NSCopying>
__attribute__((objc_subclassing_restricted))
@interface GPBUnknownField : NSObject<NSCopying>
/** Initialize a field with the given number. */
- (instancetype)initWithNumber:(int32_t)number;

@ -39,7 +39,8 @@ NS_ASSUME_NONNULL_BEGIN
* of a message that are unknown end up in an instance of this set. This only
* applies for files declared with the "proto2" syntax.
**/
@interface GPBUnknownFieldSet : NSObject <NSCopying>
__attribute__((objc_subclassing_restricted))
@interface GPBUnknownFieldSet : NSObject<NSCopying>
/**
* Tests to see if the given field number has a value.

Loading…
Cancel
Save