Skip to content

Commit 39eafd0

Browse files
committed
Support for 2D and 3D points in Bolt V2
This commit makes driver able to send and receive 2D and 3D points. Both are represented as custom `Point2D` and `Point3D` classes that contain coordinates and coordinate reference system identifier. This identifier comes as an integer from the database. It can thus be either represented as `Integer` or native `number`, when `disableLosslessIntegers` config option is set to true.
1 parent 4b0a2a8 commit 39eafd0

File tree

7 files changed

+430
-1
lines changed

7 files changed

+430
-1
lines changed

src/v1/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import VERSION from '../version';
2929
import {assertString, isEmptyObjectOrNull} from './internal/util';
3030
import urlUtil from './internal/url-util';
3131
import HttpDriver from './internal/http/http-driver';
32+
import {Point2D, Point3D} from './spatial-types';
3233

3334
/**
3435
* @property {function(username: string, password: string, realm: ?string)} basic the function to create a
@@ -205,7 +206,9 @@ const types = {
205206
Path,
206207
Result,
207208
ResultSummary,
208-
Record
209+
Record,
210+
Point2D,
211+
Point3D
209212
};
210213

211214
/**

src/v1/internal/packstream-v2.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
*/
1919

2020
import * as v1 from './packstream-v1';
21+
import {isPoint2D, isPoint3D, Point2D, Point3D} from '../spatial-types';
22+
import {int} from '../integer';
23+
24+
const POINT_2D = 0x58;
25+
const POINT_3D = 0x59;
2126

2227
export class Packer extends v1.Packer {
2328

@@ -32,6 +37,16 @@ export class Packer extends v1.Packer {
3237
disableByteArrays() {
3338
throw new Error('Bolt V2 should always support byte arrays');
3439
}
40+
41+
packable(obj, onError) {
42+
if (isPoint2D(obj)) {
43+
return () => packPoint2D(obj, this, onError);
44+
} else if (isPoint3D(obj)) {
45+
return () => packPoint3D(obj, this, onError);
46+
} else {
47+
return super.packable(obj, onError);
48+
}
49+
}
3550
}
3651

3752
export class Unpacker extends v1.Unpacker {
@@ -43,4 +58,51 @@ export class Unpacker extends v1.Unpacker {
4358
constructor(disableLosslessIntegers = false) {
4459
super(disableLosslessIntegers);
4560
}
61+
62+
63+
_unpackUnknownStruct(signature, size, buffer) {
64+
if (signature == POINT_2D) {
65+
return unpackPoint2D(this, buffer);
66+
} else if (signature == POINT_3D) {
67+
return unpackPoint3D(this, buffer);
68+
} else {
69+
return super._unpackUnknownStruct(signature, size, buffer);
70+
}
71+
}
72+
}
73+
74+
function packPoint2D(point, packer, onError) {
75+
const packableStructFields = [
76+
packer.packable(int(point.srid), onError),
77+
packer.packable(point.x, onError),
78+
packer.packable(point.y, onError)
79+
];
80+
packer.packStruct(POINT_2D, packableStructFields, onError);
81+
}
82+
83+
function packPoint3D(point, packer, onError) {
84+
const packableStructFields = [
85+
packer.packable(int(point.srid), onError),
86+
packer.packable(point.x, onError),
87+
packer.packable(point.y, onError),
88+
packer.packable(point.z, onError)
89+
];
90+
packer.packStruct(POINT_3D, packableStructFields, onError);
91+
}
92+
93+
function unpackPoint2D(unpacker, buffer) {
94+
return new Point2D(
95+
unpacker.unpack(buffer), // srid
96+
unpacker.unpack(buffer), // x
97+
unpacker.unpack(buffer) // y
98+
);
99+
}
100+
101+
function unpackPoint3D(unpacker, buffer) {
102+
return new Point3D(
103+
unpacker.unpack(buffer), // srid
104+
unpacker.unpack(buffer), // x
105+
unpacker.unpack(buffer), // y
106+
unpacker.unpack(buffer) // z
107+
);
46108
}

src/v1/internal/server-version.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,14 @@ function compareInts(x, y) {
111111

112112
const VERSION_3_1_0 = new ServerVersion(3, 1, 0);
113113
const VERSION_3_2_0 = new ServerVersion(3, 2, 0);
114+
const VERSION_3_4_0 = new ServerVersion(3, 4, 0);
114115
const VERSION_IN_DEV = new ServerVersion(0, 0, 0);
115116

116117
export {
117118
ServerVersion,
118119
VERSION_3_1_0,
119120
VERSION_3_2_0,
121+
VERSION_3_4_0,
120122
VERSION_IN_DEV
121123
};
122124

src/v1/spatial-types.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Copyright (c) 2002-2018 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import {int} from './integer';
21+
22+
const POINT_2D_IDENTIFIER_PROPERTY = '__isPoint2D__';
23+
const POINT_3D_IDENTIFIER_PROPERTY = '__isPoint3D__';
24+
25+
/**
26+
* Represents a single two-dimensional point in a particular coordinate reference system.
27+
*/
28+
export class Point2D {
29+
30+
/**
31+
* @constructor
32+
* @param {number|Integer} srid the coordinate reference system identifier.
33+
* @param {number} x the <code>x</code> coordinate of the point.
34+
* @param {number} y the <code>y</code> coordinate of the point.
35+
*/
36+
constructor(srid, x, y) {
37+
this.srid = int(srid);
38+
this.x = x;
39+
this.y = y;
40+
}
41+
}
42+
43+
Object.defineProperty(Point2D.prototype, POINT_2D_IDENTIFIER_PROPERTY, {
44+
value: true,
45+
enumerable: false,
46+
configurable: false
47+
});
48+
49+
/**
50+
* Represents a single tree-dimensional point in a particular coordinate reference system.
51+
*/
52+
export class Point3D {
53+
54+
/**
55+
* @constructor
56+
* @param {number|Integer} srid the coordinate reference system identifier.
57+
* @param {number} x the <code>x</code> coordinate of the point.
58+
* @param {number} y the <code>y</code> coordinate of the point.
59+
* @param {number} z the <code>z</code> coordinate of the point.
60+
*/
61+
constructor(srid, x, y, z) {
62+
this.srid = int(srid);
63+
this.x = x;
64+
this.y = y;
65+
this.z = z;
66+
}
67+
}
68+
69+
Object.defineProperty(Point3D.prototype, POINT_3D_IDENTIFIER_PROPERTY, {
70+
value: true,
71+
enumerable: false,
72+
configurable: false
73+
});
74+
75+
/**
76+
* Test if given object is an instance of {@link Point2D} class.
77+
* @param {object} obj the object to test.
78+
* @return {boolean} <code>true</code> if given object is a {@link Point2D}, <code>false</code> otherwise.
79+
*/
80+
export function isPoint2D(obj) {
81+
return hasProperty(obj, POINT_2D_IDENTIFIER_PROPERTY);
82+
}
83+
84+
/**
85+
* Test if given object is an instance of {@link Point3D} class.
86+
* @param {object} obj the object to test.
87+
* @return {boolean} <code>true</code> if given object is a {@link Point3D}, <code>false</code> otherwise.
88+
*/
89+
export function isPoint3D(obj) {
90+
return hasProperty(obj, POINT_3D_IDENTIFIER_PROPERTY);
91+
}
92+
93+
function hasProperty(obj, name) {
94+
return (obj && obj[name]) === true;
95+
}

test/types/v1/spatial-types.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Copyright (c) 2002-2018 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import {Point2D, Point3D} from "../../../types/v1/spatial-types";
21+
import Integer, {int} from "../../../types/v1/integer";
22+
23+
const point1: Point2D = new Point2D(int(1), 2, 3);
24+
const srid1: Integer = point1.srid;
25+
const x1: number = point1.x;
26+
const y1: number = point1.y;
27+
28+
const point2: Point2D<number> = new Point2D(1, 2, 3);
29+
const srid2: number = point2.srid;
30+
const x2: number = point2.x;
31+
const y2: number = point2.y;
32+
33+
const point3: Point3D = new Point3D(int(1), 2, 3, 4);
34+
const srid3: Integer = point3.srid;
35+
const x3: number = point3.x;
36+
const y3: number = point3.y;
37+
const z3: number = point3.z;
38+
39+
const point4: Point3D<number> = new Point3D(1, 2, 3, 4);
40+
const srid4: number = point4.srid;
41+
const x4: number = point4.x;
42+
const y4: number = point4.y;
43+
const z4: number = point4.z;

0 commit comments

Comments
 (0)