blob: 775d7e7bc5b67bdaabe87f21e3af8e56434d9a3a [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import Foundation
public struct Advertisement {
public typealias AdId = NSData // size 16
public typealias Attributes = [String: String]
public typealias Attachments = [String: NSData]
/// Universal unique identifier of the advertisement.
/// If this is not specified, a random unique identifier will be assigned.
public let adId: AdId?
/// Interface name that the advertised service implements.
/// E.g., 'v.io/v23/services/vtrace.Store'.
public let interfaceName: String
/// Addresses (vanadium object names) that the advertised service is served on.
/// E.g., '/host:port/a/b/c', '/ns.dev.v.io:8101/blah/blah'.
public let addresses: [String]
/// Attributes as a key/value pair.
/// E.g., {'resolution': '1024x768'}.
///
/// The key must be US-ASCII printable characters, excluding the '=' character
/// and should not start with '_' character.
///
/// We limit the maximum number of attachments to 32.
public let attributes: Attributes?
/// Attachments as a key/value pair.
/// E.g., {'thumbnail': binary_data }.
///
/// Unlike attributes, attachments are for binary data and they are not queryable.
///
/// The key must be US-ASCII printable characters, excluding the '=' character
/// and should not start with '_' character.
///
/// We limit the maximum number of attachments to 32 and the maximum size of each
/// attachment is 4K bytes.
public let attachments: Attachments?
public init(id adId: AdId?, interfaceName: String, addresses: [String], attributes: Attributes? = nil, attachments: Attachments? = nil) {
self.adId = adId
self.interfaceName = interfaceName
self.addresses = addresses
self.attributes = attributes
self.attachments = attachments
}
public func toJsonable() -> [String: AnyObject] {
var json = [String: AnyObject]()
if let id = adId {
json["Id"] = id.base64EncodedStringWithOptions([])
}
json["InterfaceName"] = interfaceName
json["Addresses"] = addresses
if let attrs = attributes {
json["Attributes"] = attrs
}
if let a = attachments {
var attachments = [String: String]()
for (key, data) in a {
attachments[key] = data.base64EncodedStringWithOptions([])
}
json["Attachments"] = attachments
}
return json
}
public enum JsonErrors: ErrorType {
case InvalidJsonData
}
public static func fromJsonable(data: [String: AnyObject]) throws -> Advertisement {
guard let adIdBytes = data["Id"] as? NSArray,
let ifaceName = data["InterfaceName"] as? String,
let addresses = data["Addresses"] as? [String],
let attributes = data["Attributes"] as? [String: String]?,
let attachmentsBytes = data["Attachments"] as? [String: NSArray]? else {
throw JsonErrors.InvalidJsonData
}
let adId = adIdBytes.toNSData()
let attachments = attachmentsBytes?.reduce([String: NSData](), combine: { (acc, elem) in
var ret = acc
ret[elem.0] = elem.1.toNSData()
return ret
})
return Advertisement(
id: adId,
interfaceName: ifaceName,
addresses: addresses,
attributes: attributes,
attachments: attachments)
}
}