Argument for BrowserBridge methods is stringified JSON array of stringified JSON parameters - updated to facilitate import:
- Classes potentially used as JS argument templates can define this state by subclassing JSArgumentBase - JSBridgeArgumentWrap now unpacks and deserialises each stringified parameter - Argument template state automatically applied as argument types are defined
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
#include "Connector/Interface/Browser/Bridge/Base/GetDocumentInfo.h"
|
||||
|
||||
#include "Active/Serialise/CargoHold.h"
|
||||
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h"
|
||||
|
||||
using namespace active::container;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "Connector/Interface/Browser/Bridge/Base/GetDocumentState.h"
|
||||
|
||||
#include "Active/Serialise/CargoHold.h"
|
||||
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
|
||||
#include "Connector/Database/Model/Card/ModelCardDatabase.h"
|
||||
|
||||
using namespace active::container;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Connector/Interface/Browser/Bridge/Config/Arg/ConnectorConfig.h"
|
||||
|
||||
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
|
||||
#include "Active/Serialise/Package/PackageWrap.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -11,11 +12,13 @@ namespace {
|
||||
|
||||
///Serialisation fields
|
||||
enum FieldIndex {
|
||||
arg0,
|
||||
darkTheme,
|
||||
};
|
||||
|
||||
///Serialisation field IDs
|
||||
static std::array fieldID = {
|
||||
Identity{"0"},
|
||||
Identity{"DarkTheme"},
|
||||
};
|
||||
|
||||
@@ -30,6 +33,9 @@ namespace {
|
||||
--------------------------------------------------------------------*/
|
||||
bool ConnectorConfig::fillInventory(Inventory& inventory) const {
|
||||
using enum Entry::Type;
|
||||
//When used as an argument template, this wrapper is expected to be first in the list
|
||||
if (isArgumentTemplate())
|
||||
inventory.merge({ fieldID[arg0], arg0, element });
|
||||
inventory.merge(Inventory{
|
||||
{
|
||||
{ fieldID[darkTheme], darkTheme, element },
|
||||
@@ -51,6 +57,9 @@ Cargo::Unique ConnectorConfig::getCargo(const Inventory::Item& item) const {
|
||||
return nullptr;
|
||||
using namespace active::serialise;
|
||||
switch (item.index) {
|
||||
case arg0:
|
||||
//This structure is the first argument
|
||||
return std::make_unique<PackageWrap>(*this);
|
||||
case darkTheme:
|
||||
return std::make_unique<ValueWrap<bool>>(isDarkTheme);
|
||||
default:
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
#define CONNECTOR_INTERFACE_BRIDGE_CONNECTOR_CONFIG
|
||||
|
||||
#include "Active/Serialise/Package/Package.h"
|
||||
#include "Speckle/Interface/Browser/Bridge/JSArgumentBase.h"
|
||||
|
||||
namespace connector::interfac::browser::bridge {
|
||||
|
||||
/*!
|
||||
Configuration settings class
|
||||
*/
|
||||
class ConnectorConfig : public active::serialise::Package {
|
||||
class ConnectorConfig : public active::serialise::Package, virtual public speckle::interfac::browser::bridge::JSArgumentBase {
|
||||
public:
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
@@ -29,11 +29,7 @@ namespace connector::interfac::browser::bridge {
|
||||
speckle::utility::String ID;
|
||||
int32_t count = 0;
|
||||
bool testBool = false;
|
||||
|
||||
/* Id = GetHashCode() + " - I am a string",
|
||||
count = GetHashCode(),
|
||||
thisIsABoolean = false
|
||||
*/
|
||||
|
||||
// MARK: - Serialisation
|
||||
|
||||
/*!
|
||||
|
||||
@@ -17,11 +17,11 @@ namespace {
|
||||
isHelloID,
|
||||
};
|
||||
|
||||
///Serialisation field IDs
|
||||
///Serialisation field IDs. NB: This structure is never exported, so we only define the incoming argument indices
|
||||
static std::array fieldID = {
|
||||
Identity{"name"},
|
||||
Identity{"count"},
|
||||
Identity{"sayHelloNotHi"},
|
||||
Identity{"0"},
|
||||
Identity{"1"},
|
||||
Identity{"2"},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef SPECKLE_INTERFACE_JS_BRIDGE_ARGUMENT_BASE
|
||||
#define SPECKLE_INTERFACE_JS_BRIDGE_ARGUMENT_BASE
|
||||
|
||||
#include "Active/Serialise/Package/Package.h"
|
||||
#include "Speckle/Utility/String.h"
|
||||
|
||||
namespace speckle::interfac::browser::bridge {
|
||||
|
||||
/*!
|
||||
Interface for objects used as arguments for JS bridge arguments
|
||||
|
||||
Enables deserialisation to recognise individual parameters in the serialised JS method aergument, e.g. "0", "1", etc
|
||||
*/
|
||||
class JSArgumentBase {
|
||||
public:
|
||||
/*!
|
||||
Destructor
|
||||
*/
|
||||
virtual ~JSArgumentBase() {}
|
||||
|
||||
// MARK: - Functions (const)
|
||||
|
||||
/*!
|
||||
Determine if the object is used as an argument template
|
||||
@return True if the object is used as an argument template
|
||||
*/
|
||||
bool isArgumentTemplate() const { return m_isArgumentTemplate; }
|
||||
|
||||
// MARK: - Functions (mutating)
|
||||
|
||||
/*!
|
||||
Set whether the object is used as an argument template
|
||||
@param state True if the object is used as an argument template
|
||||
*/
|
||||
void setArgumentTemplate(bool state) { m_isArgumentTemplate = state; }
|
||||
|
||||
private:
|
||||
///True if the object is used as an argument template
|
||||
bool m_isArgumentTemplate = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //SPECKLE_INTERFACE_JS_BRIDGE_ARGUMENT_BASE
|
||||
@@ -2,6 +2,7 @@
|
||||
#define SPECKLE_INTERFACE_JS_BRIDGE_ARGUMENT
|
||||
|
||||
#include "Active/Serialise/Package/Package.h"
|
||||
#include "Speckle/Interface/Browser/Bridge/JSArgumentBase.h"
|
||||
#include "Speckle/Utility/String.h"
|
||||
|
||||
namespace speckle::interfac::browser::bridge {
|
||||
@@ -95,13 +96,18 @@ namespace speckle::interfac::browser::bridge {
|
||||
class JSArgType : public JSBridgeArgument {
|
||||
public:
|
||||
using JSBridgeArgument::JSBridgeArgument;
|
||||
|
||||
|
||||
JSArgType() {
|
||||
//Tag the argument object as a template where possible
|
||||
if (auto arg = dynamic_cast<JSArgumentBase*>(&value); arg != nullptr)
|
||||
arg->setArgumentTemplate(true);
|
||||
}
|
||||
/*!
|
||||
Copy constructor
|
||||
@param source The object to copy
|
||||
*/
|
||||
JSArgType(const JSArgType& source) : JSBridgeArgument{ source }, value{ source.value } {}
|
||||
|
||||
JSArgType(const JSArgType& source) : JSBridgeArgument{source}, value{source.value} {}
|
||||
|
||||
T value;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
#include "Active/Serialise/Inventory/Inventory.h"
|
||||
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
|
||||
#include "Active/Serialise/Package/Wrapper/ValueSettingWrap.h"
|
||||
#include "Active/Serialise/JSON/JSONTransport.h"
|
||||
#include "Active/Utility/BufferIn.h"
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace active::serialise::json;
|
||||
using namespace active::setting;
|
||||
using namespace speckle::interfac::browser::bridge;
|
||||
using namespace speckle::utility;
|
||||
|
||||
@@ -41,7 +43,7 @@ namespace {
|
||||
{ {"arg"}, args, 0, std::nullopt, true }, //The JS arguments are expressed as a flat array - use the array indices to map to expected vars
|
||||
},
|
||||
}.withType(&typeid(JSBridgeArgumentWrap));;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
@@ -131,7 +133,24 @@ std::unique_ptr<JSBridgeArgument> JSBridgeArgumentWrap::makeArgument(const Strin
|
||||
if (auto maker = m_argumentFactory.find(methodID); (maker != m_argumentFactory.end())) {
|
||||
if (auto result = reinterpret_cast<JSBridgeArgument*>(maker->second(methodID, requestID)); result != nullptr) {
|
||||
try {
|
||||
JSONTransport().receive(std::forward<Cargo&&>(*result), Identity{}, argument);
|
||||
//The argument is passed as an array of stringified JSON - first unpack the array
|
||||
JSONTransport transport;
|
||||
ValueSetting args;
|
||||
transport.receive(ValueSettingWrap{args}, Identity{}, argument);
|
||||
//Then unify the argument strings into a single JSON argument
|
||||
String unifiedArgument{"{"};
|
||||
int32_t argIndex = 0;
|
||||
bool isFirst = false;
|
||||
for (auto& arg : args.operator std::vector<active::utility::String>()) {
|
||||
if (isFirst)
|
||||
isFirst = false;
|
||||
else
|
||||
unifiedArgument += ",";
|
||||
unifiedArgument += "\"" + String{argIndex++} + "\":" + JSONTransport::convertFromJSONString(arg);
|
||||
}
|
||||
unifiedArgument += "}";
|
||||
//And receive the unified argument into the methiod argument
|
||||
transport.receive(std::forward<Cargo&&>(*result), Identity{}, unifiedArgument);
|
||||
return std::unique_ptr<JSBridgeArgument>{result};
|
||||
} catch(std::runtime_error e) {
|
||||
//Populating the error cancels the method
|
||||
|
||||
@@ -19,7 +19,11 @@ namespace speckle::interfac::browser::bridge {
|
||||
template<typename T>
|
||||
void* constructArgument(const speckle::utility::String& method, const speckle::utility::String& request) {
|
||||
try {
|
||||
return new T(method, request);
|
||||
auto result = new T(method, request);
|
||||
//Tag the argument object as a template where possible
|
||||
if (auto arg = dynamic_cast<JSArgumentBase*>(result); arg != nullptr)
|
||||
arg->setArgumentTemplate(true);
|
||||
return result;
|
||||
} catch(...) {
|
||||
return nullptr; //Object constructors should throw an exception if incoming data isn't viable (NB: only use for unrecoverable problems)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
210CC86F2C7E879700610F58 /* JSArgumentBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 210CC86D2C7E879700610F58 /* JSArgumentBase.h */; };
|
||||
212A88132AE48821001EAFE7 /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21379E082AE47A6400A1584C /* libArchicad27.a */; platformFilters = (macos, ); };
|
||||
2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351782C624FC100E5A69C /* MenuSubscriber.cpp */; };
|
||||
2193518C2C62655700E5A69C /* MenuEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 219351892C62655700E5A69C /* MenuEvent.h */; };
|
||||
@@ -69,6 +70,7 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
210CC86D2C7E879700610F58 /* JSArgumentBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArgumentBase.h; sourceTree = "<group>"; };
|
||||
212A87EF2AE4868C001EAFE7 /* SpeckleLib-test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SpeckleLib-test.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
21329F472BFA611C00B5C7AF /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
21329F632BFD452C00B5C7AF /* Environment.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Environment.md; sourceTree = "<group>"; };
|
||||
@@ -312,6 +314,7 @@
|
||||
21F69F4A2C6CCC25008B6A06 /* BrowserBridge.cpp */,
|
||||
21F69F4B2C6CCC25008B6A06 /* BrowserBridge.h */,
|
||||
21F69F582C6CDAEE008B6A06 /* Functions */,
|
||||
210CC86D2C7E879700610F58 /* JSArgumentBase.h */,
|
||||
21F69FA52C733EDA008B6A06 /* JSBridgeArgument.cpp */,
|
||||
21F69F4D2C6CCC25008B6A06 /* JSBridgeArgument.h */,
|
||||
21F69F802C6FF3B0008B6A06 /* JSBridgeArgumentWrap.cpp */,
|
||||
@@ -385,6 +388,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
21F69F5A2C6CDB67008B6A06 /* FunctionBinding.h in Headers */,
|
||||
210CC86F2C7E879700610F58 /* JSArgumentBase.h in Headers */,
|
||||
21B67D0D2C7E0E8D00FD64FC /* ErrorReport.h in Headers */,
|
||||
21B67D002C7CE15100FD64FC /* Exception.h in Headers */,
|
||||
2193518C2C62655700E5A69C /* MenuEvent.h in Headers */,
|
||||
|
||||
Reference in New Issue
Block a user