Add base85 extension to NSData

PiperOrigin-RevId: 731381576
This commit is contained in:
Guogang Li
2025-02-26 11:02:30 -08:00
committed by Copybara-Service
parent 45d6317a64
commit 5c3cc4eb71
5 changed files with 148 additions and 0 deletions
@@ -0,0 +1,35 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSData (GNCBase85)
/** Creates a Base85 encoded string from the data using websafe characters and no padding. */
- (NSString *)base85EncodedString;
/**
* Initializes a data object with the given Base85 encoded string.
*
* @param base85String A Base85 encoded string.
* @return A data object built by Base85 decoding the provided string. Returns @c nil if the data
* object could not be decoded.
*/
- (nullable instancetype)initWithBase85EncodedString:(NSString *)base85String;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,49 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "internal/platform/implementation/apple/Mediums/BLEv2/NSData+GNCBase85.h"
#import <Foundation/Foundation.h>
#include <optional>
#include <string>
#include "internal/encoding/base85.h"
#import "GoogleToolboxForMac/GTMLogger.h"
@implementation NSData (GNCBase85)
- (NSString *)base85EncodedString {
const char *data = static_cast<const char *>(self.bytes);
NSUInteger length = self.length;
std::optional<std::string> base85String =
nearby::encoding::Base85Encode(std::string(data, length));
if (!base85String.has_value()) {
return @"";
}
return @(base85String->c_str());
}
- (nullable instancetype)initWithBase85EncodedString:(NSString *)base85String {
std::optional<std::string> decodedData =
nearby::encoding::Base85Decode(std::string(base85String.UTF8String));
if (!decodedData.has_value()) {
return nil;
}
return [NSData dataWithBytes:decodedData->data() length:decodedData->size()];
}
@end
@@ -29,6 +29,7 @@ objc_library(
"BLEv2/GNCCentralManager.m",
"BLEv2/GNCPeripheral.m",
"BLEv2/GNCPeripheralManager.m",
"BLEv2/NSData+GNCBase85.mm",
"BLEv2/NSData+GNCWebSafeBase64.m",
"Ble/GNCMBleConnection.m",
"Ble/GNCMBleUtils.mm",
@@ -51,6 +52,7 @@ objc_library(
"BLEv2/GNCCentralManager.h",
"BLEv2/GNCPeripheral.h",
"BLEv2/GNCPeripheralManager.h",
"BLEv2/NSData+GNCBase85.h",
"BLEv2/NSData+GNCWebSafeBase64.h",
"Ble/GNCMBleConnection.h",
"Ble/GNCMBleUtils.h",
@@ -62,6 +64,7 @@ objc_library(
"WiFiCommon/GNCNWFrameworkSocket.h",
],
deps = [
"//internal/encoding:base85",
"//internal/platform/implementation/apple:Shared",
"//internal/platform/implementation/apple/Mediums/Ble/Sockets:Shared",
"//proto/mediums:ble_frames_cc_proto",
@@ -44,6 +44,7 @@ objc_library(
"GNCScheduledExecutorTest.mm",
"GNCSingleThreadExecutorTest.mm",
"GNCUtilsTest.mm",
"NSData+GNCBase85Test.m",
"NSData+GNCWebSafeBase64Test.m",
],
deps = [
@@ -0,0 +1,60 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import "internal/platform/implementation/apple/Mediums/BLEv2/NSData+GNCBase85.h"
#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>
@interface NSData_GNCBase85Test : XCTestCase
@end
@implementation NSData_GNCBase85Test
- (void)testEncoding {
NSString *expected = @"@:E^";
NSData *data = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
NSString *actual = [data base85EncodedString];
XCTAssertEqualObjects(expected, actual);
}
- (void)testEncodingDataWithZero {
NSString *expected = @"z";
NSData *data = [@"\0\0" dataUsingEncoding:NSUTF8StringEncoding];
NSString *actual = [data base85EncodedString];
XCTAssertEqualObjects(expected, actual);
}
- (void)testDecoding {
NSData *data = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
NSString *actual = [data base85EncodedString];
NSData *decodedData = [[NSData alloc] initWithBase85EncodedString:actual];
XCTAssertEqualObjects(decodedData, data);
}
- (void)testEncodingEmptyData {
XCTAssertEqualObjects([[@"" dataUsingEncoding:NSUTF8StringEncoding] base85EncodedString], @"");
}
- (void)testDecodingEmptyData {
XCTAssertEqualObjects([[NSData alloc] initWithBase85EncodedString:@""],
[@"" dataUsingEncoding:NSUTF8StringEncoding]);
}
- (void)testDecodingInvalidString {
NSString *invalidString = @"invalid";
XCTAssertNil([[NSData alloc] initWithBase85EncodedString:invalidString]);
}
@end