-
-
Save dislick/914e67444f8f71df3900bd77ccec6091 to your computer and use it in GitHub Desktop.
/** | |
* Convert a sematic versioning string into an 32-bit integer. | |
* | |
* Make sure the input string is compatible with the standard found | |
* at semver.org. Since this only uses 10-bit per major/minor/patch version, | |
* the highest possible SemVer string would be 1023.1023.1023. | |
* @param {string} version SemVer string | |
* @return {number} Numeric version | |
*/ | |
const convertVersionToInt32 = function(version) { | |
// Split a given version string into three parts. | |
let parts = version.split('.'); | |
// Check if we got exactly three parts, otherwise throw an error. | |
if (parts.length !== 3) { | |
throw new Error('Received invalid version string'); | |
} | |
// Make sure that no part is larger than 1023 or else it | |
// won't fit into a 32-bit integer. | |
parts.forEach((part) => { | |
if (part >= 1024) { | |
throw new Error(`Version string invalid, ${part} is too large`); | |
} | |
}); | |
// Let's create a new number which we will return later on | |
let numericVersion = 0; | |
// Shift all parts either 0, 10 or 20 bits to the left. | |
for (let i = 0; i < 3; i++) { | |
numericVersion |= parts[i] << i * 10; | |
} | |
return numericVersion; | |
}; | |
/** | |
* Converts a 32-bit integer into a semantic versioning (SemVer) compatible string. | |
* @param {number} v Numeric version | |
* @return {string} SemVer string | |
*/ | |
const convertInt32VersionToString = function(v) { | |
// Works by shifting the numeric version to the right and then masking it | |
// with 0b1111111111 (or 1023 in decimal). | |
return `${v & 1023}.${v >> 10 & 1023}.${v >> 20 & 1023}` | |
}; |
@mangoser Thanks! Your Java rewrite looks nice!
How can this be used for order?
For example:
convertVersionToInt32('1.0.1')
-> 1048577
convertVersionToInt32('2.0.0')
-> 2
A solution in shell (bash) for your coammnd-line scripts: semver2number.sh
Note that the Most Significant Number is from left to right so you can compare the ints for less than and greater than.
How can this be used for order?
For example:
convertVersionToInt32('1.0.1')
->1048577
convertVersionToInt32('2.0.0')
->2
For sort order you're probably better off just doing zero-padding. See this example:
const versionPadded = version => version.split('.').map((n, i) => n.padStart(3, '0')).join('');
versionToInt("4.50.1") // == 004005001
If you care about performance doing the same kind of thing using Math.pow is actually faster: https://jsperf.com/sortable-version
Hemm I think there is some bug in your code..
convertVersionToInt32('1.1.1')
// 1049601
convertVersionToInt32('1.0.1')
// 1048577
so far so good right, but when I input
convertVersionToInt32('2.1.0')
// 1026
convertVersionToInt32('2.1.0') > convertVersionToInt32('1.1.1')
// it return false, should true 2.1.0 is grather than 1.1.1
Hemm I think there is some bug in your code..
The integers produced by this function were never meant to be sortable. The goal was to encode a semver string in a 32-bit integer.
Actually it can convert to a sortable int easily.
Checkout my fork: https://gist.github.com/yeganemehr/2468c2b28acde8f34dd170db65f05f62
Thank you so much for this simple & brilliant work.
I have forked your gist and rewrote for Java: https://gist.github.com/alpay/eae52237f08c47f72f542e48899ae547